使用反射调用静态方法

我在名称空间 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 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 中的所有静态类中调用所有 Run 方法。马克罗斯。

126805 次浏览

MethodInfo 的文档所述,静态方法的第一个参数被忽略,因此您可以只传递 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);

通过只创建一次委托(也不需要实例化类来调用静态方法) ,您可以真正、真正、真正优化您的代码。我也做过类似的事情,我只是在一个 helper 类的帮助下将一个委托缓存到“ 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 的 type-cast 和 typeof 替换为任何所需的 Action 和 Func 泛型类型,或者声明并使用它。我自己的实现使用 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);
}
}

我更喜欢简单。

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);

类,该类将调用这些方法:

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

使用 反射调用 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

伟大的资源: