2016-01-05 26 views
2

我試圖讓一個事件系統特效的ArgumentException:方法的參數是不兼容的

我有這樣的功能插件靜態類,讓我的任何基本的事件處理程序鏈接到任何基本的事件,不管班每一個對象,只要他們有需要的功能

這裏是功能

(與多個真正有用的通用功能的一個公共靜態類

public static bool eventLinker<T,Y>(T listener, Y speaker, string eventName, string eventHandler) 
{ 
    EventInfo eInfo = typeof(Y).GetEvent(eventName); 
    MethodInfo evHandler = typeof(T).GetMethod(eventHandler, new Type[2] {typeof(object), typeof(EventArgs)}); 
    Type handlerType = eInfo.EventHandlerType; 

    if(eInfo != null && evHandler != null && handlerType != null) 
    { 

     Delegate d = Delegate.CreateDelegate(handlerType, speaker, evHandler); 
     eInfo.AddEventHandler(listener,d); 

     return true; 
    } 
    return false; 
} 

這應該適用於任何具有 公共事件EventHandler SomethingHappened的課程;

public void nameOfTheFunctionThatTriggerTheEvent() 
{ 
    EventHandler handler = SomethingHappened; 
    if(handler != null) 
    { 
     handler(this, EventArgs.Empty); 
    } 

} 

與誰擁有

public void HandleEvent(object sender, EventArgs e) 
{ 
    Debug.Log("Something happened to " + sender); 
} 

我總是在Delegate.CreateDelegate得到這個錯誤

ArgumentException的任何類:方法參數不兼容 System.Delegate.CreateDelegate(System.Type的類型,System.Object firstArgument,System.Reflection.MethodInfo方法,布爾型 throwOnBindFailure)(在 /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/Delegate.cs:263) System.Delegate.CreateDelegate(System.Type type,System.Object firstArgument, System.Reflection.MethodInfo方法)(位於 /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/Delegate.cs:276) FunctionExt.eventLinker [效果,測試] (.Effect listener,.Test speaker, System.String eventName,System.String eventHandler)(在 Assets/_C#/ FunctionExt.cs:41)GameUpdate.Awake()(在 Assets/_C#/ GameUpdate.cs :84)

我在任何地方都找不到解決方案。

回答

1

首先AddEventHandler需要將目標作爲第一個參數,並且您傳遞的是不正確的偵聽器。

接下來,當您創建委託時,您應該使用另一個方法簽名CreateDelegate,因爲將從處理程序調用傳遞第一個參數(請參閱您的代碼handler(this, EventArgs.Empty);)。

整個代碼:

public static bool eventLinker<T, Y>(T listener, Y speaker, string eventName, string eventHandler) 
{ 
    EventInfo eInfo = typeof(Y).GetEvent(eventName); 
    MethodInfo evHandler = typeof(T).GetMethod(eventHandler, new Type[2] { typeof(object), typeof(EventArgs) }); 
    Type handlerType = eInfo.EventHandlerType; 

    if (eInfo != null && evHandler != null && handlerType != null) 
    { 
     Delegate d = Delegate.CreateDelegate(handlerType, listener, eventHandler); 
     eInfo.AddEventHandler(speaker, d); 

     return true; 
    } 
    return false; 
} 

或者你可以使用現有的創建委託的事件處理程序的檢查替代更通用和安全代碼:

public static bool eventLinker<T, Y>(T listener, Y speaker, string eventName, string eventHandler) 
{ 
    EventInfo eInfo = typeof(Y).GetEvent(eventName); 
    Type handlerType = eInfo.EventHandlerType; 

    if (eInfo != null && handlerType != null) 
    { 
     Delegate d = Delegate.CreateDelegate(handlerType, listener, eventHandler, false, false); 
     if (d != null) 
     { 
      eInfo.AddEventHandler(speaker, d); 
      return true; 
     } 
    } 
    return false; 
} 

最後一個例子沒有硬編碼處理參數typeof(object), typeof(EventArgs),然後可以使用自定義事件類型處理場景。

+0

哇謝謝!我曾嘗試像這樣的解決方案,但我有聽衆和揚聲器顛倒 –

+0

即時通訊仍然是新的反思和所有msdn例如過於複雜的空無 我的意思是,唯一的例子是接近我想要做的是一個關於如何在運行時創建一個全班的教程,所以它真的很讓人困惑。 MSDN教程是最糟糕的 –

+0

MSDN示例通常過於簡單,但XML文檔和參數說明可能很有用。例如,在[CreateDelegate](https://msdn.microsoft.com/en-us/library/74x8f551(v = vs.110).aspx)中,它是一個奇怪的參數名稱(對我的意見而言)firstArgument,但對評論我們可以看到明確的解釋「委託綁定到的對象,或者將方法視爲靜態的爲null」。我從來沒有使用過CreateDelegate,但只有MSDN修復你的代碼30-40分鐘。 –

0

你的錯誤是在該行:

Delegate d = Delegate.CreateDelegate(handlerType, speaker, evHandler); 
eInfo.AddEventHandler(listener,d); 

AddEventHandler想知道你要綁定的delegateevent。所以它必須是:

Delegate d = Delegate.CreateDelegate(handlerType, listener, evHandler); 
eInfo.AddEventHandler(speaker,d); 

我試過了。我花了一段時間,直到我明白了。

+0

謝謝,用於在運行時爲事件創建委託的msdn教程非常令人困惑,我不知道爲什麼,但他們也必須告訴您如何在運行時同時創建整個類。那些教程是最糟糕的 –

相關問題