Delegate.CreateDelegate() and generics: Error binding to target method

10,463

That is because the overload of Delegate.CreateDelegate only supports creating delegates pointing to static methods. If you want to bind to instance methods, you also need to pass in the instance on which your created delegate is supposed to call the method.

You probably want:

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

Also, your code example won't compile. You can't declare variance on method signatures; and you can't omit the implementation in a non-abstract class.

Finally, Delegate.CreateDelegate creates a Delegate instance, which cannot exist without knowing it's type parameters. Therefore, you cannot bind to classyDelegate<,>, you need to know the actual types involved.

Share:
10,463
SDReyes
Author by

SDReyes

“Courage brother, do not stumble, though thy path be dark as night: There is a star to guide the humble, trust in God, and do the right. Let the road be dark and dreary and its end far out of sight. Face it bravely, strong or weary. Trust God, and do”

Updated on June 19, 2022

Comments

  • SDReyes
    SDReyes almost 2 years

    I'm having problems creating a collection of delegate using reflection and generics.

    I'm trying to create a delegate collection from Ally methods, whose share a common method signature.

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

    And the generics cooking:

    // 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( );
    

    But the Delegate.CreateDelegate( delegateType, method ) throws an ArgumentException saying Error binding to target method. : /

    What am I doing wrong?

  • SDReyes
    SDReyes about 14 years
    Hi Driis! thank you for your response. What do you mean with 'You can't declare variance on method signatures'?
  • gix
    gix about 14 years
    He means the out and in keywords on your generic arguments.
  • driis
    driis about 14 years
    I mean that you can't have the out and in modifiers on your method signatures in the class. You can only have them on delegate and interface declarations.
  • SDReyes
    SDReyes about 14 years
    Ok! I undestand now. ...correcting... Thanks you very much: ) +1 +1
  • SDReyes
    SDReyes about 14 years
    @driis So I have to make use of MakeGenericType() to create a delegate typed accordingly. right?
  • driis
    driis about 14 years
    @SDReyes, Yes I think you need to go that way.
  • Jean Hominal
    Jean Hominal about 12 years
    -1: As the documentation explains, the Delegate.CreateDelegate(Type,MethodInfo) overload can also create delegates for instance methods. (e.g. it is possible to create a delegate for ToString() by using CreateDelegate(typeof(Func<Object, String>), toStringMethodInfo), after which toStringDelegate(someObject) will be equivalent to someObject.ToString(). This is called an "open instance delegate", and it is very useful.