简体   繁体   English

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

[英]Call methods using names in C#

I have a number of 'jobs' in my application, where each job has a list of methods which it needs to call, along with it's parameters. 我的应用程序中有许多“作业”,每个作业都有一个需要调用的方法列表以及其参数。 Essentially a list containing the following object is called: 本质上,包含以下对象的列表称为:

string Name;
List<object> Parameters;

So basically, when a job runs I want to enumerate through this list, and call the relevant methods. 因此,基本上,当作业运行时,我想通过此列表进行枚举,并调用相关方法。 For example, if I have a method like the following: 例如,如果我有如下方法:

TestMethod(string param1, int param2)

My method object would be like this: 我的方法对象是这样的:

Name = TestMethod
Parameters = "astring", 3

Is it possible to do this? 是否有可能做到这一点? I imagine reflection will be the key here. 我想反射将是关键。

Sure, you can do it like this: 当然,您可以这样做:

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

The second parameter of Invoke() is an array of Object containing all the parameters to pass to your method. Invoke()的第二个参数是一个Object数组,其中包含所有要传递给您的方法的参数。

Assuming the methods all belong to the same class, you could have a method of that class something like: 假设所有方法都属于同一类,则可以使用该类的方法,例如:

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

如果您使用的是.NET Framework 4,请查看dynamic ,否则查看GetMethod ,然后Invoke MethodInfo Invoke

NuGet to the rescue! Nu抢救! PM> Install-Package dnpextensions

Once you have that package in your project, all objects should now have a .InvokeMethod() extension, that will take the method name as a string and any number of parameters. 在项目中拥有该程序包后,所有对象现在都应具有.InvokeMethod()扩展名,该扩展名将方法名作为字符串和任意数量的参数。

That does technically use "magic strings" for the method names, so if you wanted to strongly-type your method dictionary, you could make the keys of type MethodInfo and get them like this... 从技术上讲,这确实使用了“魔术字符串”作为方法名称,因此,如果您想对方法字典进行强类型输入,则可以输入MethodInfo类型的键并按如下方式获取它们:

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

And then you can do something like this... 然后您可以执行类似的操作...

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.

Or you could do some variation of the above block using the dnpextensions I mentioned earlier. 或者,您可以使用我前面提到的dnpextensions对上述块进行一些更改。

Use MethodBase.Invoke() . 使用MethodBase.Invoke() Should work down to .NET 2.0 with System.Reflection . 应该使用System.Reflection降级到.NET 2.0。

If you're using having to resort to reflection, there is probably a better way to accomplish your task. 如果您不得不求助于反思,那么可能会有更好的方法来完成任务。 It may take a little more architecture, but it's doable. 它可能需要更多的体系结构,但是是可行的。

Remember, having more code isn't a bad thing -- especially when it compliments the readability and manageability of your code. 请记住,拥有更多代码不是一件坏事-尤其是当它补充了代码的可读性和可管理性时。 Reflection is difficult to understand for most, and you lose most of your compile time type safety. 对于大多数人来说,反射是很难理解的,并且会损失大部分编译时类型的安全性。 In your example, you could probably just get away with a switch statement and distinct objects for each method you were planning to call. 在您的示例中,您可能只打算使用switch语句和打算调用的每种方法使用不同的对象。 eg 例如

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

If you know that you only have a distinct set of method possibilities to call, why not just set yourself up ahead of time? 如果您知道只有几种独特的方法可以调用,为什么不提前设置自己呢?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM