[英]Using Reflection Invoke static generic method passing a Lamba as parameter
是否可以通过Reflection编写以下代码?
var fake = A.Fake<Foo>(
o => o.WithArgumentsForConstructor(new[] { "Hello" }));
o在哪里:
Action<IFakeOptionsBuilder<T>>
其中WithArgumentsForConstructor是:
IFakeOptionsBuilder<T> WithArgumentsForConstructor(IEnumerable<object> argumentsForConstructor);
Foo类是:
class Foo
{
public Foo(string s)
{
}
}
我所做的是:
object fake = typeof(A)
.GetMethod("Fake", new Type[] { })
.MakeGenericMethod(new[] { this.targetType })
.Invoke(null, /* Here I need to pass the lambda. */);
是的,可以通过反思来做您建议的事情,但是完全没有必要。 像这样自己定义一个静态方法会更简单:
public static class MyClass
{
public static T CreateFakeWithArgumentsForConstructor<T>(object[] argumentsForConstructor)
{
return A.Fake<T>(x => x.WithArgumentsForConstructor(argumentsForConstructor));
}
}
现在,只需使用反射调用此函数:
var method = typeof(MyClass).GetMethod("CreateFakeWithArgumentsForConstructor", BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(new[] { theType });
method.Invoke(null, argumentsForConstructor);
如果我正确理解了该问题,则可以使用以下命令:
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 });
与Foo
一样被视为:
class Foo
{
public Foo(string one, string two)
{
}
}
最后! :)
困难的部分是,在运行时,我不知道类型,因此泛型不是一个选择(甚至在私有帮助器方法上也不是)。
该方案将能够执行此操作:
var fake = new Fake<Foo>(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);
}
奇迹般有效。 :)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.