ArgumentException : method arguments are incompatible

11,797

Solution 1

First of all AddEventHandler requires target as a first parameter and you are passing listener that is not right.

Next, when you create delegate you should use another method signature CreateDelegate because first parameter will be passed from handler invocation (see your code handler(this, EventArgs.Empty);).

The whole code:

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

Or you can use alternative more generic and safety code with check of event handler existing on create delegate:

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

Last example have no hard-coded handler parameters typeof(object), typeof(EventArgs) and then can handle scenarios with custom event types.

Solution 2

if you were using Unity (IF), I had the same problem, and all I had to do is make another object of whatever element is making this problem then just copy the components from the inspector of the object that is causing the problem and paste it to the new object you made, and it worked, Idk why but it did, just make sure you copy and paste every component from the inspector and paste it into a new one.

Share:
11,797
Cedric Raymond
Author by

Cedric Raymond

Updated on June 04, 2022

Comments

  • Cedric Raymond
    Cedric Raymond almost 2 years

    I am trying to make an event system for special effects

    I have this function ins a static class to allow me to link any basic event handler to any basic event, no matter the classes of each objects, as long as they have the needed functions

    here is the function

    (in a public static class with multiple really useful generic functions

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

    this should work wich any classes who have public event EventHandler SomethingHappened;

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

    with any class who have

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

    I always get this error at Delegate.CreateDelegate

    ArgumentException: method arguments are incompatible System.Delegate.CreateDelegate (System.Type type, System.Object firstArgument, System.Reflection.MethodInfo method, Boolean throwOnBindFailure) (at /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 method) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/Delegate.cs:276) FunctionExt.eventLinker[Effect,Test] (.Effect listener, .Test speaker, System.String eventName, System.String eventHandler) (at Assets/_C#/FunctionExt.cs:41) GameUpdate.Awake () (at Assets/_C#/GameUpdate.cs:84)

    I could not find the solution anywhere.

  • Cedric Raymond
    Cedric Raymond over 8 years
    Wow thanks!, i did try solutions like this one but i had listener and speaker reversed
  • Cedric Raymond
    Cedric Raymond over 8 years
    im still new with reflections and all msdn exemple are over complicated for nothing i mean, the only exemple that were close to what i was trying to do was also a tutorial on how to create a whole class on run time so it was really confusing. msdn tutorial are the worst
  • Cedric Raymond
    Cedric Raymond over 8 years
    thanks, the msdn tutorial for creating delegate on runtime for events was so confusing, i dont know why but they HAD to also show you how to create a whole class in runtime at the same time. Those tutorial are the worst
  • Vadim Martynov
    Vadim Martynov over 8 years
    MSDN examples is often too simple, but XML-docs and parameters description can be useful. For example, in CreateDelegate it's a strange argument name (for my opinion) firstArgument, but on comments we can see unambiguous explanation "The object to which the delegate is bound, or null to treat method as static". I never used CreateDelegate before but with only MSDN fix your code for 30-40 minutes.
  • Tel
    Tel over 3 years
    in Unity this worked for me; happened after I copied and pasted some elements from one scene into another -- had to delete/reassign some scripts/methods
  • ow3n
    ow3n over 3 years
    This is exactly what happened for me too. Specifically it was a TextMeshPro dropdown that had previously been assigned in a different scene. Just drag the new reference and set the correct method and done.