基于数组中包含的字符串值调用/调用方法

时间:2012-03-26 20:29:41

标签: c# .net-3.5 methods

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

我想将方法​​名存储在struct-array中,然后让程序在匹配时调用该方法。这可能吗?

目前:

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

理想情况下:

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

更新

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

7 个答案:

答案 0 :(得分:6)

你可以使用 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});

更好的方法是根据您的方法定义委托,并将其存储在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>的预定义类型,而不是定义自己的委托类型,具体取决于您是否需要从报告中返回值。

答案 1 :(得分:3)

您可以存储委托:

,而不是存储方法名称
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”的方法的调用。混乱。

答案 2 :(得分:2)

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

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

答案 3 :(得分:1)

是的,你所说的是reflectionHere is an article on how to invoke a method。您可以使用谷歌在反思中找到很多。

答案 4 :(得分:1)

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

答案 5 :(得分:1)

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

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

答案 6 :(得分:0)

使用delegatedictionary<string, delegate>

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