用反射调用静态方法

Ton*_*Nam 102 c# reflection dynamic

我在命名空间中有几个静态类,mySolution.Macros例如

static class Indent{    
     public static void Run(){
         // implementation
     }
     // other helper methods
}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是如何在反射的帮助下调用这些方法?

如果方法不是静态的那么我可以做类似的事情:

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);
}
Run Code Online (Sandbox Code Playgroud)

我想让我的课程保持静态.我怎么能用静态方法做类似的事情?

简而言之,我想从命名空间mySolution.Macros中的所有静态类调用所有Run方法.

Lee*_*Lee 137

正如MethodInfo.Invoke文档所述,静态方法会忽略第一个参数,因此您只能传递null.

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

正如评论指出的那样,您可能希望在调用时确保该方法是静态的GetMethod:

tempClass.GetMethod("Run", BindingFlags.Public | BindingFlags.Static).Invoke(null, null);
Run Code Online (Sandbox Code Playgroud)

  • 你可能想把一些绑定标志传递给`GetMethod`. (4认同)
  • 没有`BindingFlags.Static`,您可能无法成功地获得该方法。 (2认同)

Lou*_*ier 18

通过只花一次创建委托的代价,你可以真正地,真正地,真正地优化你的代码(也没有必要实例化类来调用静态方法).我做了一些非常相似的事情,我只是在助手类的帮助下将一个委托缓存到"Run"方法:-).它看起来像这样:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

这种方式更快.

如果您的方法签名与Action不同,您可以将类型转换和typeof从Action替换为任何所需的Action和Func泛型类型,或者声明您的Delegate并使用它.我自己的实现使用Func来打印漂亮的对象:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)


Mim*_*ina 6

将调用方法的类:

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

使用Reflection调用 myClass 静态方法:

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());
Run Code Online (Sandbox Code Playgroud)

注意:我不需要实例化 myClass 的对象来使用它的方法,因为我使用的方法是static.

丰富的资源: