How to Invoke Methods Using MethodInfo in C

In C#, reflection allows developers to inspect metadata and interact with types dynamically at runtime. This article provides a clear overview of the MethodInfo class and demonstrates how to dynamically discover and invoke both instance and static methods at runtime using the System.Reflection namespace.

What is the MethodInfo Class?

The MethodInfo class belongs to the System.Reflection namespace and represents metadata about a specific method. It provides access to method attributes, return types, parameters, and access modifiers. Beyond reading metadata, its primary utility is providing the Invoke method, which enables late-bound execution of methods without compile-time binding.

Obtaining a MethodInfo Instance

To invoke a method dynamically, you must first obtain its MethodInfo object using the Type class via Type.GetMethod(). By default, GetMethod() only returns public methods, but you can pass BindingFlags to search for private, internal, or static members.

using System;
using System.Reflection;

Type type = typeof(Calculator);

// Retrieve a public instance method
MethodInfo addMethod = type.GetMethod("Add");

// Retrieve a private or static method using BindingFlags
MethodInfo logMethod = type.GetMethod("Log", BindingFlags.NonPublic | BindingFlags.Static);

Invoking Methods Dynamically

The MethodInfo.Invoke method takes two arguments:

  1. The target object: The instance of the class that contains the method. For static methods, this argument must be null.
  2. Parameters: An object[] array containing the arguments to pass to the method. If the method takes no parameters, pass null.

The Invoke method returns an object, which can be cast to the expected return type.

Complete Example

using System;
using System.Reflection;

public class Calculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }

    private static void PrintResult(string message)
    {
        Console.WriteLine($"Output: {message}");
    }
}

class Program
{
    static void Main()
    {
        Type calcType = typeof(Calculator);
        object calcInstance = Activator.CreateInstance(calcType);

        // 1. Invoking a public instance method with parameters and return value
        MethodInfo addMethod = calcType.GetMethod("Add");
        object[] addParams = new object[] { 10, 20 };
        object result = addMethod.Invoke(calcInstance, addParams);

        Console.WriteLine($"Addition Result: {result}");

        // 2. Invoking a private static method
        MethodInfo printMethod = calcType.GetMethod(
            "PrintResult", 
            BindingFlags.NonPublic | BindingFlags.Static
        );

        object[] printParams = new object[] { result.ToString() };
        printMethod.Invoke(null, printParams);
    }
}

Exception Handling and Considerations

  • TargetInvocationException: When an invoked method throws an unhandled exception, reflection wraps it inside a TargetInvocationException. To inspect the original exception, check the InnerException property.
  • Performance: Calling methods via MethodInfo.Invoke is significantly slower than standard compile-time calls. For high-throughput scenarios, consider caching the MethodInfo object, compiling delegates via Expression trees, or using System.Reflection.Emit.
  • Overloaded Methods: If a method has overloads, calling GetMethod("MethodName") throws an AmbiguousMatchException. Resolve this by specifying parameter types: type.GetMethod("Add", new Type[] { typeof(int), typeof(int) }).