2010-04-26 12 views
8

我在使用反射和泛型創建委託集合時遇到了問題。Delegate.CreateDelegate()和泛型:錯誤綁定到目標方法

我試圖從盟友方法創建一個代表集合,其共享一個共同的方法簽名。

public class Classy 
{ 
    public string FirstMethod<T1, T2>(string id, Func<T1, int, IEnumerable<T2>> del); 
    public string SecondMethod<T1, T2>(string id, Func<T1, int, IEnumerable<T2>> del);  
    public string ThirdMethod<T1, T2>(string id, Func<T1, int, IEnumerable<T2>> del); 

    // And so on... 
} 

而且仿製藥烹調:

// This is the Classy's shared method signature  
public delegate string classyDelegate<out T1, in T2>(string id, Func<T1, int, IEnumerable<T2>> filter); 


// And the linq-way to get the collection of delegates from Classy 
( 
    from method in typeof(Classy).GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.NonPublic) 
    let delegateType = typeof(classyDelegate<,>) 
    select Delegate.CreateDelegate(delegateType, method) 
).ToList(); 

但是,Delegate.CreateDelegate(delegateType, method)引發ArgumentException說錯誤綁定到目標方法。 :/

我在做什麼錯?

回答

16

這是因爲Delegate.CreateDelegate的重載只支持創建指向靜態方法的委託。如果要綁定到實例方法,則還需要傳入創建的委託應該調用該方法的實例。

你可能想:

from method in typeof(Classy).GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.NonPublic) 
let delegateType = typeof(classyDelegate<,>) 
select Delegate.CreateDelegate(delegateType, yourInstance, method) 

此外,您的代碼示例將無法編譯。您不能在方法簽名上聲明方差;並且您不能在非抽象類中省略實現。

最後,Delegate.CreateDelegate創建一個代理實例,如果不知道它是類型參數就不能存在。因此,你不能綁定到classyDelegate,>,你需要知道涉及的實際類型。

+0

嗨Driis!感謝您的答覆。 「你不能在方法簽名上聲明方差」是什麼意思? – SDReyes 2010-04-26 16:31:39

+3

他意味着你的泛型參數中的'out'和'in'關鍵字。 – gix 2010-04-26 16:32:53

+1

我的意思是說,你不能在你的方法簽名的類中使用修飾符。你只能在委託和接口聲明上擁有它們。 – driis 2010-04-26 16:33:44