关于C#:使用反射调用静态方法 |
您所在的位置:网站首页 › 反射方法内部的方法如何调用 › 关于C#:使用反射调用静态方法 |
我在名称空间mySolution.Macros中有几个静态类,例如 123456static class Indent{ public static void Run(){ // implementation } // other helper methods }所以我的问题是,在反射的帮助下如何调用这些方法? 如果方法不是静态的,那么我可以做些类似的事情: 12345678910var 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); }我想让我的课保持静态。 如何使用静态方法执行类似的操作? 简而言之,我想从名称空间mySolution.Macros中的所有静态类中调用所有Run方法。 正如MethodInfo.Invoke的文档所述,静态方法将忽略第一个参数,因此您可以仅传递null。 12345foreach (var tempClass in macroClasses) { // using reflection I will be able to run the method as: tempClass.GetMethod("Run").Invoke(null, null); }正如注释所指出的那样,您可能需要确保在调用GetMethod时该方法是静态的: 1tempClass.GetMethod("Run", BindingFlags.Public | BindingFlags.Static).Invoke(null, null); 相关讨论 您可能希望将一些绑定标志传递给GetMethod。 如果没有BindingFlags.Static,您可能无法首先成功获取该方法... 如果该方法位于祖先类中,则可能需要添加BindingFlags.FlattenHierarchy。您只需付出一次创建委托的代价,就可以确实,确实,真正地大大优化了代码(也无需实例化该类以调用静态方法)。我做过非常类似的事情,我只是在一个助手类的帮助下将委托缓存到"运行"方法中:-)。看起来像这样: 12345678910111213141516171819202122232425262728293031static 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 macroRunners; public static void Run() { foreach(var run in macroRunners) run(); } }这样的速度要快得多。 如果您的方法签名与Action不同,则可以将Action的类型转换和typeof替换为任何所需的Action和Func泛型类型,或者声明您的Delegate并使用它。我自己的实现使用Func漂亮地打印对象: 123456789101112131415161718192021222324static class PrettyPrinter { static PrettyPrinter() { BuildPrettyPrinterList(); } static void BuildPrettyPrinterList() { printers = System.Reflection.Assembly.GetExecutingAssembly() .GetTypes() .Where(x => x.Name.EndsWith("PrettyPrinter")) .Select(t => (Func)Delegate.CreateDelegate( typeof(Func), null, t.GetMethod("Print", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public))) .ToList(); } static List printers; public static void Print(object obj) { foreach(var printer in printers) print(obj); } }我更喜欢简单... 123456789private 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 { } } } }用法... 1 _InvokeNamespaceClassesStaticMethod("mySolution.Macros","Run");但是如果您正在寻找更强大的功能,包括异常处理... 1234567891011121314151617181920212223242526272829303132333435363738394041private InvokeNamespaceClassStaticMethodResult[] _InvokeNamespaceClassStaticMethod(string namespaceName, string methodName, bool throwExceptions, params object[] parameters) { var results = new List(); 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; }用法几乎相同... 1_InvokeNamespaceClassesStaticMethod("mySolution.Macros","Run", false); 相关讨论 吞下任何可能的异常通常是一个坏主意。 真正。 这很懒,但是很简单。 香港专业教育学院提高了我的答案。 不是很干净的代码或不容易阅读 |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |