Blog Post

Invoke an overloaded generic method with parameters using reflection

Ideas & Innovation
Invoke an overloaded generic method with parameters using reflection
  • 17
    Jun
  • Image

Invoke an overloaded generic method with parameters using reflection


Add this invoke method as an extension to the Type class

I have been working on an ASP.NET web forms application recently where I was using Unity as my inversion of control (IoC) container and I needed a way to build up my dependencies automatically. To do this I had to Invoke a generic method using reflection passing both the type arguments and parameters to the method. I won't focus on how I achieved automatic build up of my dependencies within my web application, I will only detail a component that helped me along the way.

Problem:

  1. Invoke a method using reflection
  2. Invoke a generic method using reflection
  3. Invoke an extension method via reflection
  4. Pass parameters to this method during invocation

Solution:

public static class TypeExtensions
{
    /// 
    /// Invoke a generic method using reflection
    /// 
    /// Type containing the method for invocation
    /// Method to invoke (case sensitive)
    /// Generic type arguments
    /// Method parameters
    /// Object returned from method invocation call
    public static object InvokeGenericMethod(
        this Type type,
        string methodName,
        Type[] typeArguments,
        object[] parameters)
    {
        // Since this method is for generic types
        if(typeArguments == null || typeArguments.Length == 0)
            throw new ArgumentException("Type arguments must be supplied", "typeArguments");

        MethodInfo[] resolveMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Static);

        // Ensure that the method we invoke matches the
        // name, type arguments count and number of parameters
        var methodsMatchBasicCheck = resolveMethods
            .Where(
                mi => mi.Name == methodName &&
                mi.GetGenericArguments().Count() == typeArguments.Length &&
                (parameters != null)
                    ? mi.GetParameters().Count() == parameters.Length 
                    : mi.GetParameters().Count() == 1 /* At least 1 parameter (Extension instance) */)
            .ToArray();

        // Take first match.
        // NOTE: Another filter is necessary to make a more precise
        // selection when base on the type arguments and parameters
        // there are multiple possible methods available.
        MethodInfo resolveMethod = methodsMatchBasicCheck.FirstOrDefault();

        if (resolveMethod == null)
            return null;

        // Invoke method
        MethodInfo genericResolveMethod = resolveMethod.MakeGenericMethod(typeArguments);
        return genericResolveMethod.Invoke(null, parameters);
    }
}

I created an extension method for the Type class which takes the following parameters:

  1. The name of the method to Invoke
  2. The generic type arguments (Use array length to determine number of arguments)
  3. The method parameters (Use array length to determine the number of parameters)
The extension method does a great job of solving our problem. This can be improved upon, but I will leave that for the stellar developer community out there. Feel free to post any of your improvements in the comments section below.

Using the solution:

Now one of the most critical parts to any article is demonstrating how to use the code provided. Always important but quite often forgotten. The following example is contrived but demonstrates the usage.

Debug.WriteLine(
    typeof (StringExtensions).InvokeGenericMethod
        (
            "Sum",
            new[] {typeof (int), typeof (double)},
            new object[] {"Sum: ", 5, 5.5D}
        )
    );
public static class StringExtensions
{
    public static string Sum<T1, T2>(this String s, T1 val1, T2 val2)
        where T1 : IConvertible
        where T2 : IConvertible
    {
        return String.Format("{0}{1}", s,
               (val1.ToInt32(CultureInfo.InvariantCulture.NumberFormat) +
                val2.ToInt32(CultureInfo.InvariantCulture.NumberFormat)));
    }
}

The StringExtensions class which really wanted to be a MathExtensions (the Math class is static so not an option) class contains the generic extension method with 3 parameters if you include the object of type being extended (this String s), two generic arguments and returns a string. With one simple call the method is invoked and the result of 11 is written to the debug window.

I hope you enjoyed the article and don't forget to leave feedback.

Comments (8)

Exaltación Brito Reynoso 22 April 2012, 12:52 PM Website

After research a couple of of the weblog posts on your web site now, and I truly like your means of blogging. I bookmarked it to my bookmark web site list and shall be checking back soon. Pls take a look at my site as nicely and let me know what you think.

bookmarking 08 May 2012, 03:21 AM Website

I really liked your article.Really looking forward to read more. Really Great.

service 08 May 2012, 03:51 PM Website

Thank you for your post.Really looking forward to read more. Great.

social 11 May 2012, 08:42 PM Website

jBpytq Major thankies for the blog article. Really Cool.

Diego 19 May 2012, 04:33 AM Website

Knocked my socks off with knowdlege!

This is the precise blog for anybody who wants to search out out about this topic. You notice a lot its virtually hard to argue with you (not that I truly would want…HaHa). You positively put a brand new spin on a topic thats been written about for years. Great stuff, simply nice!

Jothyi Maximusl 01 July 2012, 01:24 AM Website

If any one wishes to be a successful blogger, afterward he/she must look at this piece of writing, as it consists of al} techniques related to that.

.Net Training 26 February 2013, 04:35 AM Website

The determination of type difference is not based on the generic type parameter, but on the type argument substituted for the type parameter when a constructed type is created.

New Comment

Notify me of follow up posts