2011-06-24 74 views
16

我的应用程序中有许多'作业',其中每个作业都有一个需要调用的方法列表及其参数。主要包含以下对象的列表被称为:在C#中使用名称的调用方法

string Name; 
List<object> Parameters; 

因此,基本上,当一个作业运行我想通过这个列表枚举,并调用相关的方法。举例来说,如果我有类似下面的方法:

TestMethod(string param1, int param2) 

我的方法的对象会是这样的:

Name = TestMethod 
Parameters = "astring", 3 

是否有可能做到这一点?我想在这里反思将是关键。

回答

35

当然,你可以像这样做:

public class Test 
{ 
    public void Hello(string s) { Console.WriteLine("hello " + s); } 
} 

... 

{ 
    Test t = new Test(); 
    typeof(Test).GetMethod("Hello").Invoke(t, new[] { "world" }); 

    // alternative if you don't know the type of the object: 
    t.GetType().GetMethod("Hello").Invoke(t, new[] { "world" }); 
} 

调用的第二个参数()是一个包含所有参数Object数组传递到您的方法。

假设所有属于同一个类中的方法,你可以有该类类似的方法:

public void InvokeMethod(string methodName, List<object> args) 
{ 
    GetType().GetMethod(methodName).Invoke(this, args.ToArray()); 
} 
+0

神奇,正是我在找的。谢谢 :) – Chris

1

如果您使用的是.NET Framework 4,请看dynamic,否则GetMethod,然后拨打电话InvokeMethodInfo

+0

我不难过,我在3.5 – Chris

-1

如果您使用不得不求助于反思,那么可能有更好的方法来完成您的任务。它可能需要更多的架构,但它是可行的。请记住,拥有更多代码并不是一件坏事 - 尤其是当它支持代码的可读性和可管理性时。大多数情况下,反射很难理解,并且会丢失大部分编译时类型安全性。在你的例子中,你可能只是为了你打算调用的每个方法而放弃switch语句和不同的对象。例如

// Have some object hold the type of method it plans on calling. 
enum methodNames 
{ 
    Method1, 
    Method2 
} 

... 
class someObject 
{ 
    internal methodNames methodName {get; set;} 
    internal object[] myParams; 
} 
... 

// Execute your object based on the enumeration value it references. 
switch(someObject1.methodName) 
{ 
    case Method1: 
     Test.Method1(Int32.Parse(someObject1.myParams[0].ToString),someObject1.myParams[1].ToString()); 
     break; 
    ... 
} 

如果你知道你只有一组不同的方法调用,为什么不直接设置自己呢?

1

NuGet救援! PM> Install-Package dnpextensions

一旦你在你的项目中有了这个包,所有对象现在应该有一个.InvokeMethod()扩展名,它将把方法名称作为一个字符串和任意数量的参数。

但这在技术上使用“魔术字符串”的方法名称,因此,如果你想强键入法词库,你可以做类型的MethodInfo的钥匙,让他们这样的...

MethodInfo[] methodInfos = typeof(MyClass).GetMethods(); 

然后你就可以做这样的事情......

var methods = new Dictionary<MethodInfo, Object[]>(); 
foreach (var item in methods) 
    item.key.Invoke(null, item.value); 
    // 'null' may need to be an instance of the object that 
    // you are calling methods on if these are not static methods. 

或者你可以用做我前面提到的dnpextensions上述区块的一些变化。