我有一个方法和两个委托,如下所示。它以这种方式运行。但我想使用Delegate.CreateInstance。 dx和dy的类型必须为Func<IEnumerable<Foo>>
。就像下面的fx和fy。它们不能是Func<int, IEnumerable<Foo>>
。
public class Test {
private IEnumerable<T> CreateItems<T>(int count) where T : class
{
for (int i = 0; i < count; i++)
{
yield return (T)Activator.CreateInstance(typeof(T), i.ToString());
}
}
public List<T> TestMethod<T>(int i = 1) where T : class
{
return CreateItems<T>(i).ToList();
}
public void TestRun()
{
const int Count = 5;
Func<IEnumerable<Foo>> fx = () => this.TestMethod<Foo>(Count);
Func<IEnumerable<Foo>> fy = () => this.TestMethod<Foo>();
var lfx = fx.Invoke();
var lfy = fy.Invoke();
var dx = Delegate.CreateDelegate( ?? );
var dy = Delegate.CreateDelegate( ?? );
var ldx = dx.DynamicInvoke();
var ldy = dy.DynamicInvoke();
}
}
答案 0 :(得分:2)
那是不可能的。您无法直接将带有签名A F(X x)
的实例方法放入Func<A>
。
可以直接将方法的第一个参数绑定到委托中,但不能添加其他参数。在您的情况下,实例this
是第一个参数,您无法绑定i
的值。
我猜你的误解是默认值的参数是如何工作的。它们仍然是调用者需要填写的参数。这只是C#编译器为你做的。
你需要一个带有正确签名的包装器。这可以是lambda或其他一些辅助方法。在您的情况下,我会重载方法TestMethod
而不是使用默认参数。
答案 1 :(得分:2)
如果您希望类型为Func<IEnumerable<Foo>>
,则无法通过Delegate.CreateDelegate
直接创建 ,因为它们需要两个参数:实例(又名this
),和整数i
。即使fx
中显示的表单还有i
- 它恰好由编译器提供。如果TestMethod
没有参数,可以通过以下方式完成:
var dy = (Func<IEnumerable<Foo>>) Delegate.CreateDelegate(
typeof(Func<IEnumerable<Foo>>),
this,
GetType().GetMethod("TestMethod").MakeGenericMethod(typeof(Foo))
);
要动态执行此操作(部分应用程序),您需要创建一个具有实例(this
)的类型,要注入的值(i
)以及使用这些值调用 TestMethod<Foo>
。这是完全编译器为您做的事情:
Func<IEnumerable<Foo>> fx = () => this.TestMethod<Foo>(Count);
这基本上创造了:
internal class <>_squiggle {
public Test @this;
public IEnumerable<Foo> Method() {
return @this.TestMethod<Foo>(5);
}
}
和
var capture = new <>_squiggle { @this = this };
var fx = new Func<IEnumerable<Foo>>(capture.Method);