Delegate.CreateDelegate() and generics: Error binding to target method
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.
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, 2022Comments
-
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 about 14 yearsHi Driis! thank you for your response. What do you mean with 'You can't declare variance on method signatures'?
-
gix about 14 yearsHe means the
out
andin
keywords on your generic arguments. -
driis about 14 yearsI 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 about 14 yearsOk! I undestand now. ...correcting... Thanks you very much: ) +1 +1
-
SDReyes about 14 years@driis So I have to make use of
MakeGenericType()
to create a delegate typed accordingly. right? -
driis about 14 years@SDReyes, Yes I think you need to go that way.
-
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 forToString()
by usingCreateDelegate(typeof(Func<Object, String>), toStringMethodInfo)
, after whichtoStringDelegate(someObject)
will be equivalent tosomeObject.ToString()
. This is called an "open instance delegate", and it is very useful.