Invoking generic method with type constraint at runtime

  • Thread starter Thread starter Anders Borum
  • Start date Start date
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.
 
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]
 
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 :)
 
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

Back
Top