【问题标题】:Call/Invoke a method based on a string value contained in an array [duplicate]基于数组中包含的字符串值调用/调用方法[重复]
【发布时间】:2012-03-26 20:29:41
【问题描述】:

我有一个结构数组,其中包含可以运行的不同报告的详细信息。每个报告调用不同的方法,目前程序必须手动检查选定的报告值以专门调用适当的方法。

我想将方法​​名称存储在结构数组中,然后让程序在匹配时调用该方法。这可能吗?

目前:

if (this.cboSelectReport.Text == "Daily_Unload")
{
   reportDailyUnload();
 }

理想情况下:

if(this.cboSelectReport.Text == MyArray[i].Name)
{
   something(MyArray[i].MethodName);
}

更新

我厌倦了下面的一些建议,但都没有奏效。他们没有工作可能是因为我的程序结构如何。

【问题讨论】:

    标签: c# .net-3.5 methods


    【解决方案1】:

    您可以使用 reflection 来做到这一点,但 IMO 它太脆弱了:它引入了对您调用的方法名称的无形依赖。

    // Assuming that the method is static, you can access it like this:
    var namedReportMethod = "MyReport1";
    var reportMethod = typeof(ReporterClass).GetMethod(namedReportMethod);
    var res = reportMethod.Invoke(null, new object[] {reportArg1, reportArg2});
    

    更好的方法是根据您的方法定义一个 delegate,并将其存储在 struct/class 而不是方法名称中。

    delegate void ReportDelegate(int param1, string param2);
    
    class Runner {
        public static void RunReport(ReportDelegate rd) {
            rd(1, "hello");
        }
    }
    
    class Test {
        static void TestReport(int a, string b) {
            // ....
        }
        public static void Main(string[] args) {
            Runner.RunReport(TestReport);
        }
    }
    

    您可以使用基于Action<T1,T2,...>Func<T1,T2,R> 的预定义委托类型,而不是定义自己的委托类型,具体取决于您从报告中返回值的需要。

    【讨论】:

      【解决方案2】:

      您可以存储委托,而不是存储方法名称:

      struct ReportInfo
      {
          public string Name { get; set; }
          public Action Method { get; set; }
      }
      
      //...
      
      MyArray[0] = new ReportInfo { Name = "Daily_Unload", Action = this.reportDailyUnload };
      
      //...
      
      if(this.cboSelectReport.Text == MyArray[i].Name)
      {
          MyArray[i].Method.Invoke();
      }
      

      大多数人似乎更喜欢另一种语法,在这种语法中,您可以像调用方法一样调用委托,使用括号中的参数列表。我倾向于避免这种情况,因为被调用的东西是方法还是委托可能是模棱两可的:

      MyArray[i].Method();
      

      在这种情况下,我们正在调用由Method 属性引用的委托,但此代码也可以表示对名为“Method”的方法的调用。令人困惑。

      【讨论】:

        【解决方案3】:

        对我来说,支持简单的 switch 比处理反射、方法名称或委托的数组以及调用这些东西要容易得多:

        switch (reportType)
        {
            case "Daily_Unload":
                ReportDailyUnload();
                break;
            // ...
        }
        

        【讨论】:

          【解决方案4】:

          如果所有方法共享相同的签名,一种方法是缓存委托:

          // initialize, maybe in a constructor
          Dictionary<string, Action> nameDelegateMapping = new Dictionary<string, Action>();
          // setup the delegates
          nameDelegateMapping.Add("Daily_Unload", reportDailyUnload);
          // ... add more methods here.
          
          // later
          string methodName = this.cboSelectReport.Text;
          Action action;
          if (nameDelegateMapping.TryGetValue(methodName, out action))
          {
            action();
          }
          else
          {
            // tell user the method does not exist.
          }
          

          【讨论】:

            【解决方案5】:

            是的,你说的是reflectionHere is an article on how to invoke a method。使用 google 进行反思可以找到很多内容。

            【讨论】:

              【解决方案6】:

              将委托属性添加到您的结构(例如 Action 类型),然后在需要时调用此委托。只需将此属性设置为实例化结构实例时要调用的方法即可。

              【讨论】:

                【解决方案7】:

                使用delegatedictionary&lt;string, delegate&gt;

                void Main()
                {
                    var reports = new Dictionary<string, Report>
                    {
                        {"Daily_Unload", ReportDailyUnLoad}
                    };
                
                    var report = "Daily_Unload";
                    reports[report]();
                }
                
                delegate string Report();
                
                string ReportDailyUnLoad()
                {
                    return "daily unload report";
                }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-11-17
                  • 1970-01-01
                  相关资源
                  最近更新 更多