通过反射调用静态方法

问题描述 投票:0回答:4

我在命名空间中有几个静态类

mySolution.Macros
例如

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

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

如果方法不是静态的,那么我可以这样做:

var macroClasses = Assembly.GetExecutingAssembly().GetTypes().Where( x => x.Namespace.ToUpper().Contains("MACRO") );

foreach (var tempClass in macroClasses)
{
   var curInstance = Activator.CreateInstance(tempClass);
   // I know have an instance of a macro and will be able to run it

   // using reflection I can run the method as:
   curInstance.GetType().GetMethod("Run").Invoke(curInstance, null);
}

我想保持我的课程静态。我怎样才能用静态方法做类似的事情?

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

c# reflection dynamic
4个回答
184
投票

正如 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); }

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

GetMethod

:

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

21
投票
您可以通过只创建一次委托来真正、真的、真正地优化您的代码(也不需要实例化类来调用静态方法)。我做了一些非常类似的事情,我只是在辅助类的帮助下缓存了“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(); } }

这样要快得多。

如果您的方法签名与 Action 不同,您可以将 Action 中的类型转换和 typeof 替换为任何所需的 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); } }
    

5
投票
将调用方法的类:

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

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());
注意:我不需要实例化 myClass 的对象来使用它的方法,因为我使用的方法是 

static

丰富的资源:

  • C# 反射如何工作
  • MethodBase.调用方法

0
投票
我更喜欢简单...

private void _InvokeNamespaceClassesStaticMethod(string namespaceName, string methodName, params object[] parameters) { foreach(var _a in AppDomain.CurrentDomain.GetAssemblies()) { foreach(var _t in _a.GetTypes()) { try { if((_t.Namespace == namespaceName) && _t.IsClass) _t.GetMethod(methodName, (BindingFlags.Static | BindingFlags.Public))?.Invoke(null, parameters); } catch { } } } }

使用...

_InvokeNamespaceClassesStaticMethod("mySolution.Macros", "Run");

但是如果您正在寻找更强大的东西,包括异常处理......

private InvokeNamespaceClassStaticMethodResult[] _InvokeNamespaceClassStaticMethod(string namespaceName, string methodName, bool throwExceptions, params object[] parameters) { var results = new List<InvokeNamespaceClassStaticMethodResult>(); foreach(var _a in AppDomain.CurrentDomain.GetAssemblies()) { foreach(var _t in _a.GetTypes()) { if((_t.Namespace == namespaceName) && _t.IsClass) { var method_t = _t.GetMethod(methodName, parameters.Select(_ => _.GetType()).ToArray()); if((method_t != null) && method_t.IsPublic && method_t.IsStatic) { var details_t = new InvokeNamespaceClassStaticMethodResult(); details_t.Namespace = _t.Namespace; details_t.Class = _t.Name; details_t.Method = method_t.Name; try { if(method_t.ReturnType == typeof(void)) { method_t.Invoke(null, parameters); details_t.Void = true; } else { details_t.Return = method_t.Invoke(null, parameters); } } catch(Exception ex) { if(throwExceptions) { throw; } else { details_t.Exception = ex; } } results.Add(details_t); } } } } return results.ToArray(); } private class InvokeNamespaceClassStaticMethodResult { public string Namespace; public string Class; public string Method; public object Return; public bool Void; public Exception Exception; }

用法几乎相同...

_InvokeNamespaceClassesStaticMethod("mySolution.Macros", "Run", false);
    
© www.soinside.com 2019 - 2024. All rights reserved.