Call / Call a method based on a string value contained in an array
I have a structured array containing the details of various reports that can be run. Each report calls a different method, and currently the program needs to manually check the selected report value in order to specifically call the appropriate method.
I would like to store the name of the method in a struct array and then the program is called by that method when there is a match. Is it possible?
Currently
if (this.cboSelectReport.Text == "Daily_Unload")
{
reportDailyUnload();
}
Perfectly:
if(this.cboSelectReport.Text == MyArray[i].Name)
{
something(MyArray[i].MethodName);
}
UPDATE
I got tired of a number of suggestions below and none of them worked. They didn't work, probably because of the way I am structured in my program.
source to share
You can do it with reflection, but IMO is too fragile: it introduces an invisible dependency on the name of the method you are calling.
// 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});
A better approach would be to define a delegate based on your method and store it in a struct / class instead of the method name.
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);
}
}
Instead of defining your own delegate types, you can use predefined based on Action<T1,T2,...>
or Func<T1,T2,R>
, depending on your need, return values from reports.
source to share
Instead of storing the method name, you can store the delegate:
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();
}
Most people prefer an alternative syntax in which you can invoke the delegate as if it were a method using a parenthesized list of arguments. I try to avoid this because it can be ambiguous if the thing called is a method or a delegate:
MyArray[i].Method();
In this case, we are calling the delegate that the property refers to Method
, but this code can also be a method call. Mixing.
source to share
If all methods use the same signature, one way is to cache the delegate:
// 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.
}
source to share
Yes, what you are talking about is reflection . Here is an article on how to call a method . You can find the reflection on Google.
source to share