2011-03-21 44 views
4

我使用loadfrom加載一個dll並迭代通過這些方法來找到匹配簽名的。當我找到它的時候,我想把它作爲一個委託,所以我可以稍後調用它。這是我正在做的...試圖創建一個動態的代理

foreach (MethodInfo method in methodInfos) 
{ 
    if (method.GetParameters().Length == 2) 
    { 
     ParameterInfo[] parameters = method.GetParameters(); 
     if (parameters[0].ParameterType.Name == "Command" 
      && parameters[1].ParameterType.Name == "ExposedVariables") 
     { 
      aoc.methodinfo = method; 
      Command.delCmdMethod del = (Command.delCmdMethod) 
          Delegate.CreateDelegate(typeof(Command.delCmdMethod) 
                , null 
                , method); 
     } 
    } 
} 

問題是 - 代理分配不起作用。我得到一個錯誤綁定到目標方法。

我在網上讀到第二個參數可能是問題,如果方法不是靜態的。我的方法不是靜態的。

任何想法?

回答

0

如果該方法不是靜態的,那麼您需要傳入一個對類的實例的引用,這個類的實例將使用委託調用。

如果您不知道在您嘗試創建委託時您將使用哪個實例,則需要稍後存儲類型和方法信息,然後在獲得實例後創建委託班上。

編輯

爲了回答您的評論,你需要傳遞的對象是包含您正在嘗試將委託綁定的方法類型的對象。所以根據你的代碼示例,它不是Command對象,而是DLL中類的對象。

因此,假設您有這個.NET程序集DLL:myassembly.dll。該組件包含以下類:

namespace MyNamespace 
{ 
    public class SomeClass 
    { 
     public SomeClass() 
     { 
     } 

     public void Method1(object Command, object ExposedVariables) 
     { 
     } 

     public void Method2(object Command, object ExposedVariables) 
     { 
     } 
} 

您將需要創建類SomeClass的實例之前,你可以創建一個綁定到方法1或類的方法2名代表。因此,它創建委託的代碼應該是這樣的:

// assuming that method info is a MethodInfo contains information about the method 
// that you want to create the delegate for, create an instance of the class which 
// contains the method.. 
object classInstance = Activator.CreateInstance(methodInfo.DeclaringType); 
// and then create the delegate passing in the class instance 
Delegate.CreateDelegate(typeof(Command.delCmdMethod), classInstance, methodInfo); 
+0

我已經閱讀過這篇文章,但並不確定我需要在這裏使用哪個對象。它是命令,因爲那是委託的地方或方法所在的對象? – Jeff 2011-03-21 20:27:35

+0

首先 - 感謝迄今爲止的幫助...我按照你的說法做了, - 保存了程序集和methodinfo,然後嘗試使用上面的確切代碼創建委託,並且得到相同的錯誤。 – Jeff 2011-03-21 21:02:07

+0

您是否嘗試過使用其他程序集?我將創建一個新項目,並創建一個簡單的程序集,將其設置爲一個庫,只有一個類,例如我的例子中使用的兩個簡單方法,它們不會做任何特殊的事情,然後嘗試使用您的代碼。如果它仍然無法正常工作,請嘗試發佈更多的源代碼,我們將盡力找出答案。 – 2011-03-22 15:32:22

2

雖然Miky迪內斯庫的回答可能是有用的,它只是部分正確。對於Delegate.CreateDelegate確實存在過載,這很可能會對您有所幫助。

首先,Miky是正確的,你必須通過實例作爲第二個參數,但只有當你想創建所謂的閉合代表。這意味着一個實例與該方法一起綁定到委託。實際上,這意味着在調用委託時,它總是在同一個實例上運行。

從你的問題來看,這看起來並不是你想要達到的目標。如果您希望能夠在調用委託時傳遞實例,則必須使用CreateDelegate(Type type, MethodInfo method)過載。這使您可以創建所謂的開放實例代理

由於您在調用方法時必須傳遞實例,這意味着您的委託類型中需要額外的參數。委託類型的第一個參數需要與包含方法的類的類型相對應。

例子:

MethodInfo toUpperMethod 
    = typeof(string).GetMethod("ToUpper", new Type[] { }); 
Func<string, string> toUpper 
    = (Func<string, string>)Delegate.CreateDelegate(
      typeof(Func<string, string>), toUpperMethod); 
string upper = toUpper("test"); // Will result in "TEST". 

自 - 就像你 - 我發現這些重載不明確,我創建了兩個輔助功能清楚地分開創造一個「正常」代表或打開實例委託。此代碼以及更深入的討論can be found in my blog post