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);
}