使用C#中的名称调用方法

时间:2011-06-24 14:13:04

标签: c# reflection methods

我的应用程序中有许多“作业”,每个作业都有一个需要调用的方法列表及其参数。基本上,包含以下对象的列表称为:

string Name;
List<object> Parameters;

所以基本上,当一个作业运行时我想通过这个列表进行枚举,并调用相关的方法。例如,如果我有如下方法:

TestMethod(string param1, int param2)

我的方法对象是这样的:

Name = TestMethod
Parameters = "astring", 3

有可能这样做吗?我认为反思将成为关键。

5 个答案:

答案 0 :(得分:40)

当然,你可以这样做:

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

Invoke()的第二个参数是一个Object数组,其中包含要传递给方法的所有参数。

假设这些方法都属于同一个类,那么你可以使用类的方法:

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

答案 1 :(得分:1)

如果您使用的是.NET Framework 4,请查看dynamic,否则GetMethod,然后致电Invoke的{​​{1}}。

答案 2 :(得分: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对上面的块进行一些变化。

答案 3 :(得分:0)

使用MethodBase.Invoke()。应该使用System.Reflection来处理.NET 2.0。

答案 4 :(得分:-1)

如果你不得不求助于反思,那么可能有更好的方法来完成你的任务。它可能需要更多的架构,但它是可行的。

请记住,拥有更多代码并不是一件坏事 - 特别是当它补充代码的可读性和可管理性时。对于大多数人来说,反思很难理解,并且您失去了大部分编译时类型的安全性。在您的示例中,您可能只是为了计划调用的每个方法都使用switch语句和不同的对象。 e.g。

// 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;
   ...
}

如果你知道你只有一套独特的方法可以打电话,为什么不提前让自己好好?