Call static method with reflection

120,541

Solution 1

As the documentation for MethodInfo.Invoke states, the first argument is ignored for static methods so you can just pass null.

foreach (var tempClass in macroClasses)
{
   // using reflection I will be able to run the method as:
   tempClass.GetMethod("Run").Invoke(null, null);
}

As the comment points out, you may want to ensure the method is static when calling GetMethod:

tempClass.GetMethod("Run", BindingFlags.Public | BindingFlags.Static).Invoke(null, null);

Solution 2

You could really, really, really optimize your code a lot by paying the price of creating the delegate only once (there's also no need to instantiate the class to call an static method). I've done something very similar, and I just cache a delegate to the "Run" method with the help of a helper class :-). It looks like this:

static class Indent{    
     public static void Run(){
         // implementation
     }
     // other helper methods
}

static class MacroRunner {

    static MacroRunner() {
        BuildMacroRunnerList();
    }

    static void BuildMacroRunnerList() {
        macroRunners = System.Reflection.Assembly.GetExecutingAssembly()
            .GetTypes()
            .Where(x => x.Namespace.ToUpper().Contains("MACRO"))
            .Select(t => (Action)Delegate.CreateDelegate(
                typeof(Action), 
                null, 
                t.GetMethod("Run", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)))
            .ToList();
    }

    static List<Action> macroRunners;

    public static void Run() {
        foreach(var run in macroRunners)
            run();
    }
}

It is MUCH faster this way.

If your method signature is different from Action you could replace the type-casts and typeof from Action to any of the needed Action and Func generic types, or declare your Delegate and use it. My own implementation uses Func to pretty print objects:

static class PrettyPrinter {

    static PrettyPrinter() {
        BuildPrettyPrinterList();
    }

    static void BuildPrettyPrinterList() {
        printers = System.Reflection.Assembly.GetExecutingAssembly()
            .GetTypes()
            .Where(x => x.Name.EndsWith("PrettyPrinter"))
            .Select(t => (Func<object, string>)Delegate.CreateDelegate(
                typeof(Func<object, string>), 
                null, 
                t.GetMethod("Print", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)))
            .ToList();
    }

    static List<Func<object, string>> printers;

    public static void Print(object obj) {
        foreach(var printer in printers)
            print(obj);
    }
}

Solution 3

Class that will call the methods:

namespace myNamespace
{
    public class myClass
    {
        public static void voidMethodWithoutParameters()
        {
            // code here
        }
        public static string stringReturnMethodWithParameters(string param1, string param2)
        {
            // code here
            return "output";
        }
    }
}

Calling myClass static methods using Reflection:

var myClassType = Assembly.GetExecutingAssembly().GetType(GetType().Namespace + ".myClass");
                    
// calling my void Method that has no parameters.
myClassType.GetMethod("voidMethodWithoutParameters", BindingFlags.Public | BindingFlags.Static).Invoke(null, null);

// calling my string returning Method & passing to it two string parameters.
Object methodOutput = myClassType.GetMethod("stringReturnMethodWithParameters", BindingFlags.Public | BindingFlags.Static).Invoke(null, new object[] { "value1", "value1" });
Console.WriteLine(methodOutput.ToString());

Note: I don't need to instantiate an object of myClass to use it's methods, as the methods I'm using are static.

Great resources:

Share:
120,541
Tono Nam
Author by

Tono Nam

Updated on February 20, 2021

Comments

  • Tono Nam
    Tono Nam over 3 years

    I have several static classes in the namespace mySolution.Macros such as

    static class Indent{    
         public static void Run(){
             // implementation
         }
         // other helper methods
    }
    

    So my question is how it will be possible to call those methods with the help of reflection?

    If the methods where NOT to be static then I could do something like:

    var macroClasses = Assembly.GetExecutingAssembly().GetTypes().Where( x => x.Namespace.ToUpper().Contains("MACRO") );
    
    foreach (var tempClass in macroClasses)
    {
       var curInsance = Activator.CreateInstance(tempClass);
       // I know have an instance of a macro and will be able to run it
    
       // using reflection I will be able to run the method as:
       curInsance.GetType().GetMethod("Run").Invoke(curInsance, null);
    }
    

    I will like to keep my classes static. How will I be able to do something similar with static methods?

    In short I will like to call all the Run methods from all the static classes that are in the namespace mySolution.Macros.

  • Daniel A. White
    Daniel A. White almost 12 years
    you might want to pass some binding flags to GetMethod.
  • ErikE
    ErikE over 8 years
    Without BindingFlags.Static you may not successfully get the method in the first place...
  • D Stanley
    D Stanley over 6 years
    swallowing any possible exception is usually a bad idea.
  • dynamichael
    dynamichael over 6 years
    True. It was lazy but simple. I've improved my answer.
  • J. Ouwehand
    J. Ouwehand about 5 years
    You may want to add BindingFlags.FlattenHierarchy if the method resides in an ancestor class.