【问题标题】:Call methods using names in C#在 C# 中使用名称调用方法
【发布时间】:2011-09-22 01:54:06
【问题描述】:

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

string Name;
List<object> Parameters;

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

TestMethod(string param1, int param2)

我的方法对象是这样的:

Name = TestMethod
Parameters = "astring", 3

可以这样做吗?我想反射将是这里的关键。

【问题讨论】:

    标签: c# reflection methods


    【解决方案1】:

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

    【讨论】:

    • 在给出这个答案时,如果 .NET Framework 4 被认为是新标准还是旧标准,这将很有帮助。它目前的措辞如何,这个答案并不表明dynamic 是否也应该在 .NET Framework 上使用比 4 新或早于 4。
    【解决方案2】:

    当然,你可以这样做:

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

    【讨论】:

      【解决方案3】:

      使用MethodBase.Invoke()。应该使用System.Reflection 降到.NET 2.0。

      【讨论】:

        【解决方案4】:

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

        请记住,拥有更多代码并不是一件坏事——尤其是当它补充了代码的可读性和可管理性时。反射对大多数人来说很难理解,而且你失去了大部分编译时类型的安全性。在您的示例中,您可能只需为您计划调用的每个方法使用一个 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;
           ...
        }
        

        如果您知道只有一组不同的方法可以调用,为什么不提前设置好自己?

        【讨论】:

          【解决方案5】:

          NuGet 来救援! PM&gt; 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 对上述块进行一些变体。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-09-26
            • 2010-11-08
            • 1970-01-01
            • 1970-01-01
            • 2010-11-27
            • 2011-01-06
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多