【问题标题】:ArgumentException : method arguments are incompatibleArgumentException : 方法参数不兼容
【发布时间】:2016-01-05 19:37:40
【问题描述】:

我正在尝试为特殊效果制作一个事件系统

我有这个函数在一个静态类中,允许我将任何基本事件处理程序链接到任何基本事件,无论每个对象的类如何,只要它们具有所需的功能

这里是函数

(在具有多个非常有用的通用函数的公共静态类中

    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;
}

这应该适用于任何有 公共事件EventHandlerSomethingHappened;

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 类型,System.Object firstArgument,System.Reflection.MethodInfo 方法)(在 /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/Delegate.cs:276) FunctionExt.eventLinker[Effect,Test](.Effect 监听器,.Test 扬声器, System.String eventName, System.String eventHandler) (在 Assets/_C#/FunctionExt.cs:41) GameUpdate.Awake () (在 Assets/_C#/GameUpdate.cs:84)

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

【问题讨论】:

    标签: c# reflection unity3d delegates mono


    【解决方案1】:

    如果您使用 Unity (IF), 我遇到了同样的问题,我所要做的就是制作另一个导致此问题的元素的对象,然后只需从导致问题的对象的检查器中复制组件并将其粘贴到您制作的新对象中,然后它有效,我知道为什么,但它确实有效,只需确保从检查器复制并粘贴每个组件并将其粘贴到新组件中。

    【讨论】:

    • 在 Unity 中这对我有用;在我将一些元素从一个场景复制并粘贴到另一个场景之后发生 - 必须删除/重新分配一些脚本/方法
    • 这正是发生在我身上的事。具体来说,它是之前在不同场景中分配的 TextMeshPro 下拉菜单。只需拖动新引用并设置正确的方法即可完成。
    【解决方案2】:

    首先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),然后可以处理具有自定义事件类型的场景。

    【讨论】:

    • 哇,谢谢!,我确实尝试过这样的解决方案,但我的听者和演讲者颠倒了
    • 我仍然是新的反射和所有 msdn 示例都过于复杂,我的意思是,唯一接近我尝试做的示例也是关于如何在运行时间,所以真的很混乱。 msdn教程是最差的
    • MSDN 示例通常过于简单,但 XML 文档和参数描述可能很有用。例如,在CreateDelegate 中,firstArgument 是一个奇怪的参数名称(在我看来),但在 cmets 上我们可以看到明确的解释“委托绑定到的对象,或 null 以将方法视为静态”。我以前从未使用过 CreateDelegate,但只使用 MSDN 修复您的代码 30-40 分钟。
    【解决方案3】:

    你的错误是:

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

    AddEventHandler 想知道要将delegate 绑定到哪个event。所以它必须是:

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

    我试过了。我花了一段时间才弄明白。

    【讨论】:

    • 谢谢,在运行时为事件创建委托的 msdn 教程非常混乱,我不知道为什么,但他们还必须向您展示如何同时在运行时创建整个类。那些教程是最糟糕的
    猜你喜欢
    • 1970-01-01
    • 2019-12-14
    • 1970-01-01
    • 2019-06-18
    • 2015-06-07
    • 1970-01-01
    • 1970-01-01
    • 2013-08-09
    • 2015-09-30
    相关资源
    最近更新 更多