Invoking generic method with type constraint at runtime

A

Anders Borum

Hi

I need to invoke a generic method determined at runtime. The method has two
arguments, a string and a generic type that is constrained to a struct:

public void Add<T>(string key, T value) where T : struct

The method is an instance member located on a class called
CmsPropertyManager. I also have a number of other "Add" methods with
different overloads.

Usually, I find it quite easy to go by reflecting the type and bind to the
method, but this time it's been really hard to determine the correct binding
parameters. When I inspect the method info, I can see that the generic
argument is having a base type of System.ValueType. However, using this as
the binding signature doesn't yield any results.

// Acquire the method info (this is the part that I'm having trouble with)
MethodInfo methodInfo = typeof(CmsPropertyManager).GetMethod("Add", new
Type[] { typeof(string), typeof(System.ValueType) });

// Acquire the generic method info
MethodInfo genericInfo = methodInfo.MakeGenericMethod(type.Type);

// Invoke with a struct (represented by o)
genericInfo.Invoke(null, new object[] { this.uiKeyName.Value, o });

Please note that once I have the method / generic method info everything is
fine and dandy; that is, if I hardcode the methodinfo reference to the right
index in the reflected type (CmsPropertyManager) the rest of the reflection
part works perfectly).

Thanks in advance.
 
M

Marc Gravell

There is no single GetMethod overload that does what you want; you
need to do it manually:

static MethodInfo FindAddMethod()
{
foreach(MethodInfo method in typeof(CmsPropertyManager)
.GetMethods(BindingFlags.Public | BindingFlags.Instance))
{
if (method.Name == "Add" &&
method.IsGenericMethodDefinition)
{
Type[] typeArgs = method.GetGenericArguments();
ParameterInfo[] args = method.GetParameters();
if (typeArgs.Length == 1 && args.Length == 2
&& args[0].ParameterType == typeof(string)
&& args[1].ParameterType == typeArgs[0])
{
return method;
}
}
}
return null;
}

Marc
[C# MVP]
 
A

Anders Borum

Hi Marc,

I found a few examples like yours on the net and was curious if there's
really no other way. Then again, I guess it doesn't matter if I am the one
doing the looping instead of the reflection infrastructure. In any case,
thanks a lot for the feedback - I'm sure I can take it from here :)
 
M

Marc Gravell

If you have LINQ (.NET 3.5/C# 3.0) then you can get rid of the looping
etc - but I'll let you make your own decision as to whether it is any
simpler...

MethodInfo add = (
from method in typeof(CmsPropertyManager)
.GetMethods(BindingFlags.Public | BindingFlags.Instance)
where method.Name == "Add" && method.IsGenericMethod
let typeArgs = method.GetGenericArguments()
where typeArgs.Length == 1
let args = method.GetParameters()
where args.Length == 2
&& args[0].ParameterType == typeof(string)
&& args[1].ParameterType == typeArgs[0]
select method).Single();

Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top