Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用反射调用将Lamba作为参数传递的静态泛型方法_C#_Reflection_Lambda_Fakeiteasy - Fatal编程技术网

C# 使用反射调用将Lamba作为参数传递的静态泛型方法

C# 使用反射调用将Lamba作为参数传递的静态泛型方法,c#,reflection,lambda,fakeiteasy,C#,Reflection,Lambda,Fakeiteasy,是否可以通过反射编写以下代码 var fake = A.Fake<Foo>( o => o.WithArgumentsForConstructor(new[] { "Hello" })); 我所做的是: object fake = typeof(A) .GetMethod("Fake", new Type[] { }) .MakeGenericMethod(new[] { this.targetType }) .Invo

是否可以通过反射编写以下代码

    var fake = A.Fake<Foo>(
            o => o.WithArgumentsForConstructor(new[] { "Hello" }));
我所做的是:

object fake = typeof(A)
    .GetMethod("Fake", new Type[] { })
    .MakeGenericMethod(new[] { this.targetType })
    .Invoke(null, /* Here I need to pass the lambda. */);

如果我正确理解了这个问题,那么以下几点就可以了:

Action<IFakeOptionsBuilder<Foo>> fakeOptionsBuilderAction = 
    o => o.WithArgumentsForConstructor(new[] { "", "" });

// You need the BindingFlags as Fake() is a static method:
object fake = typeof(A)
    .GetMethod("Fake", BindingFlags.Public | BindingFlags.Static)
    .MakeGenericMethod(new[] { typeof(Foo) })
    .Invoke(null, new object[] { fakeOptionsBuilderAction });

如果我正确理解了这个问题,那么以下几点就可以了:

Action<IFakeOptionsBuilder<Foo>> fakeOptionsBuilderAction = 
    o => o.WithArgumentsForConstructor(new[] { "", "" });

// You need the BindingFlags as Fake() is a static method:
object fake = typeof(A)
    .GetMethod("Fake", BindingFlags.Public | BindingFlags.Static)
    .MakeGenericMethod(new[] { typeof(Foo) })
    .Invoke(null, new object[] { fakeOptionsBuilderAction });

是的,你可以通过思考来做你建议的事情,但这是完全不必要的。像这样自己定义静态方法会更简单:

public static class MyClass
{
    public static T CreateFakeWithArgumentsForConstructor<T>(object[] argumentsForConstructor)
    {
        return A.Fake<T>(x => x.WithArgumentsForConstructor(argumentsForConstructor));
    }
}

是的,你可以通过思考来做你建议的事情,但这是完全不必要的。像这样自己定义静态方法会更简单:

public static class MyClass
{
    public static T CreateFakeWithArgumentsForConstructor<T>(object[] argumentsForConstructor)
    {
        return A.Fake<T>(x => x.WithArgumentsForConstructor(argumentsForConstructor));
    }
}
最后!:)

困难的是,在运行时,我不知道类型,所以泛型不是一个选项(甚至在私有助手方法上也不是)

该场景能够做到这一点:

var fake = new Fake<Foo>(o => o.WithArgumentsForConstructor("Hello"));
var-fake=new-fake(o=>o.WithArgumentsForConstructor(“Hello”);
以下是我得到的解决方案:

private IEnumerable<object> argumentsForConstructor;

public object Invoke(IEnumerable<object> parameters)
{
    this.argumentsForConstructor = parameters;

    Type actionType = typeof(Action<>).MakeGenericType(
         typeof(IFakeOptionsBuilder<>).MakeGenericType(this.targetType));

    MethodInfo actionMethod = this.GetType()
        .GetMethod("SetArgumentsForConstructor", BindingFlags.Instance | BindingFlags.NonPublic)
        .MakeGenericMethod(new[] { this.targetType });

    Delegate action = Delegate.CreateDelegate(actionType, this, actionMethod);

    Type fake = typeof(Fake<>).MakeGenericType(this.targetType);
    ConstructorInfo ctor = (from ci in fake.GetConstructors(BindingFlags.Instance | BindingFlags.Public)
                            from pi in ci.GetParameters()
                            where pi.ParameterType == actionType
                            select ci).First();

    return ctor.Invoke(new[] { action });
}

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This method is used by Reflection. It describes the method that is passed in the Action<IFakeOptionsBuilder<T>> overload of the Fake<T> constructor.")]
private void SetArgumentsForConstructor<T>(IFakeOptionsBuilder<T> o)
{
    if (typeof(T).IsInterface)
    {
        return;
    }

    o.WithArgumentsForConstructor(this.argumentsForConstructor);
}
私有IEnumerable argumentsForConstructor;
公共对象调用(IEnumerable参数)
{
this.argumentsForConstructor=参数;
类型actionType=typeof(操作)。MakeGenericType(
typeof(IFakeOptionsBuilder).MakeGenericType(this.targetType));
MethodInfo actionMethod=this.GetType()
.GetMethod(“SetArgumentsForConstructor”,BindingFlags.Instance | BindingFlags.NonPublic)
.MakeGenericMethod(新[]{this.targetType});
Delegate action=Delegate.CreateDelegate(actionType,this,actionMethod);
Type fake=typeof(fake).MakeGenericType(this.targetType);
ConstructorInfo ctor=(来自假.GetConstructors(BindingFlags.Instance | BindingFlags.Public)中的ci)
来自ci.GetParameters()中的pi
其中pi.ParameterType==actionType
选择ci.First();
返回ctor.Invoke(新[]{action});
}
[System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Performance”,“CA1811:AvoidUncalledPrivateCode”,justify=“此方法由反射使用。它描述在伪构造函数的操作重载中传递的方法。”)]
专用void SetArgumentsForConstructor(IFakeOptionsBuilder o)
{
if(类型(T).IsInterface)
{
返回;
}
o、 使用argumentsForConstructor(此.argumentsForConstructor);
}
工作起来很有魅力。:)

最后!:)

困难的是,在运行时,我不知道类型,所以泛型不是一个选项(甚至在私有助手方法上也不是)

该场景能够做到这一点:

var fake = new Fake<Foo>(o => o.WithArgumentsForConstructor("Hello"));
var-fake=new-fake(o=>o.WithArgumentsForConstructor(“Hello”);
以下是我得到的解决方案:

private IEnumerable<object> argumentsForConstructor;

public object Invoke(IEnumerable<object> parameters)
{
    this.argumentsForConstructor = parameters;

    Type actionType = typeof(Action<>).MakeGenericType(
         typeof(IFakeOptionsBuilder<>).MakeGenericType(this.targetType));

    MethodInfo actionMethod = this.GetType()
        .GetMethod("SetArgumentsForConstructor", BindingFlags.Instance | BindingFlags.NonPublic)
        .MakeGenericMethod(new[] { this.targetType });

    Delegate action = Delegate.CreateDelegate(actionType, this, actionMethod);

    Type fake = typeof(Fake<>).MakeGenericType(this.targetType);
    ConstructorInfo ctor = (from ci in fake.GetConstructors(BindingFlags.Instance | BindingFlags.Public)
                            from pi in ci.GetParameters()
                            where pi.ParameterType == actionType
                            select ci).First();

    return ctor.Invoke(new[] { action });
}

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This method is used by Reflection. It describes the method that is passed in the Action<IFakeOptionsBuilder<T>> overload of the Fake<T> constructor.")]
private void SetArgumentsForConstructor<T>(IFakeOptionsBuilder<T> o)
{
    if (typeof(T).IsInterface)
    {
        return;
    }

    o.WithArgumentsForConstructor(this.argumentsForConstructor);
}
私有IEnumerable argumentsForConstructor;
公共对象调用(IEnumerable参数)
{
this.argumentsForConstructor=参数;
类型actionType=typeof(操作)。MakeGenericType(
typeof(IFakeOptionsBuilder).MakeGenericType(this.targetType));
MethodInfo actionMethod=this.GetType()
.GetMethod(“SetArgumentsForConstructor”,BindingFlags.Instance | BindingFlags.NonPublic)
.MakeGenericMethod(新[]{this.targetType});
Delegate action=Delegate.CreateDelegate(actionType,this,actionMethod);
Type fake=typeof(fake).MakeGenericType(this.targetType);
ConstructorInfo ctor=(来自假.GetConstructors(BindingFlags.Instance | BindingFlags.Public)中的ci)
来自ci.GetParameters()中的pi
其中pi.ParameterType==actionType
选择ci.First();
返回ctor.Invoke(新[]{action});
}
[System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Performance”,“CA1811:AvoidUncalledPrivateCode”,justify=“此方法由反射使用。它描述在伪构造函数的操作重载中传递的方法。”)]
专用void SetArgumentsForConstructor(IFakeOptionsBuilder o)
{
if(类型(T).IsInterface)
{
返回;
}
o、 使用argumentsForConstructor(此.argumentsForConstructor);
}

工作起来很有魅力。:)

“通过反射编写以下代码”-你是指反射。发射还是什么?lambda通常首先编译为一个表达式,您可能希望实际创建一个表达式,然后让它生成所需的IL代码。嗨,不是使用Reflection.Emit。可以使用Emit,但我希望使用System.Reflection命名空间中定义的类型。反射(不使用Emit)不会生成任何代码,但是正如我所说的,表达式是您最亲密的朋友。“通过反射编写以下代码”-您是指反射。Emit还是什么?lambda通常首先编译为一个表达式,您可能希望实际创建一个表达式,然后让它生成所需的IL代码。嗨,不是使用Reflection.Emit。可以使用Emit,但我希望使用System.Reflection命名空间中定义的类型。反射(不使用Emit)不会生成任何代码,但是正如我所说的,表达式是您最亲密的朋友。我不知道运行时的Foo:(我在运行时有ConstructorInfo和MethodInfo。我只需要通过反射传递lamdba表达式。从哪里获得要传递给构造函数的值?如果已经设置了lambda来传递正确的构造函数参数,那么我回答中的代码会通过反射传递。我还需要通过反射创建lambda。好的,和你一起。你从哪里得到传递给构造函数的值?我不知道运行时的Foo:(我在运行时有ConstructorInfo和MethodInfo。我只需要通过反射传递lamdba表达式。从哪里获得要传递给构造函数的值?如果已经设置了lambda来传递正确的构造函数参数,那么我回答中的代码会通过反射传递。我还需要通过反射创建lambda。好的,和你在一起,你从哪里得到的
private IEnumerable<object> argumentsForConstructor;

public object Invoke(IEnumerable<object> parameters)
{
    this.argumentsForConstructor = parameters;

    Type actionType = typeof(Action<>).MakeGenericType(
         typeof(IFakeOptionsBuilder<>).MakeGenericType(this.targetType));

    MethodInfo actionMethod = this.GetType()
        .GetMethod("SetArgumentsForConstructor", BindingFlags.Instance | BindingFlags.NonPublic)
        .MakeGenericMethod(new[] { this.targetType });

    Delegate action = Delegate.CreateDelegate(actionType, this, actionMethod);

    Type fake = typeof(Fake<>).MakeGenericType(this.targetType);
    ConstructorInfo ctor = (from ci in fake.GetConstructors(BindingFlags.Instance | BindingFlags.Public)
                            from pi in ci.GetParameters()
                            where pi.ParameterType == actionType
                            select ci).First();

    return ctor.Invoke(new[] { action });
}

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This method is used by Reflection. It describes the method that is passed in the Action<IFakeOptionsBuilder<T>> overload of the Fake<T> constructor.")]
private void SetArgumentsForConstructor<T>(IFakeOptionsBuilder<T> o)
{
    if (typeof(T).IsInterface)
    {
        return;
    }

    o.WithArgumentsForConstructor(this.argumentsForConstructor);
}