2012-10-19 24 views
2

我有一个方法和两个代表如下。它以这种方式运行。但我想使用Delegate.CreateInstance。 dx和dy的类型必须是Func<IEnumerable<Foo>>。就像fx和fy一样。他们不能是Func<int, IEnumerable<Foo>>如何使用Delegate.CreateDelegate而不是Func <>来定义委托?

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(); 
    } 
} 
+2

'Func键>'该类型没有按” t甚至存在。 – CodesInChaos

+1

对不起,我写错了。它是Func > – sinanakyazici

+0

委托的实际类型是你想要创建的吗?真的不清楚你想达到什么。 –

回答

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); 
+0

谢谢您的回答。但func中的方法必须从外部获取参数。我认为@CodesInChaos是正确的。可能,这是不可能的。 – sinanakyazici

+0

@sinanakyazici确实,我说“你不能通过'Delegate.CreateDelegate'直接创建。其余的内容是为什么*你不能,以及如何解决它。如果你真的很关心**,可以在运行时使用'ILGenerator'来完成,但它会变得愚蠢复杂。 –

+0

ILGenerator非常复杂。我想用这种方式来做,我希望它很简单。所以我不能使用它。这涉及我的项目的一部分。所以我需要为这部分找到一个新的东西。 – sinanakyazici

2

这是不可能的。您无法直接将实例方法与签名A F(X x)合并为Func<A>

可以将方法的第一个参数直接绑定到委托中,但没有附加参数。在你的情况下,实例this是第一个参数,并且你不能绑定i的值。

我想你的误解是如何使用默认值的参数工作。它们仍然是需要由调用者填写的参数。这只是C#编译器为你做的。

您将需要某种具有正确签名的包装。这可以是lambda或其他辅助方法。在你的情况下,我会重载方法TestMethod而不是使用默认参数。

相关问题