Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 545
SDReyes Avatar asked Apr 26 '10 16:04

SDReyes


1 Answers

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.

like image 173
driis Avatar answered Oct 08 '22 00:10

driis