4 votes

Appel/Invocation d'une méthode basée sur une valeur de type chaîne de caractères contenue dans un tableau

J'ai un tableau structuré qui contient les détails de différents rapports qui peuvent être exécutés. Chaque rapport appelle une méthode différente et actuellement le programme doit vérifier manuellement la valeur du rapport sélectionné pour appeler spécifiquement la méthode appropriée.

J'aimerais stocker le nom de la méthode dans le tableau de structure et faire en sorte que le programme invoque cette méthode en cas de correspondance. Cela est-il possible ?

Actuellement :

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

Idéalement :

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

UPDATE

J'ai essayé un certain nombre des suggestions ci-dessous, mais aucune n'a fonctionné. Ces échecs sont probablement dus à la façon dont mon programme est structuré.

6voto

dasblinkenlight Points 264350

Vous pouvez le faire en utilisant réflexion mais, à mon avis, c'est trop fragile : cela introduit une dépendance invisible au nom de la méthode que vous appelez.

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

Une meilleure approche consisterait à définir une délégué basé sur votre méthode, et le stocker dans la structure/classe au lieu du nom de la méthode.

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

Au lieu de définir vos propres types de délégués, vous pouvez utiliser des types prédéfinis basés sur les éléments suivants Action<T1,T2,...> o Func<T1,T2,R> selon votre besoin de retourner des valeurs à partir des rapports.

4voto

phoog Points 22667

Plutôt que de stocker le nom de la méthode, vous pourriez stocker un délégué :

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

La plupart des gens semblent préférer la syntaxe alternative où vous pouvez invoquer un délégué comme s'il s'agissait d'une méthode, en utilisant une liste d'arguments entre parenthèses. J'ai tendance à éviter cela, car il peut être ambigu de savoir si la chose invoquée est une méthode ou un délégué :

MyArray[i].Method();

Dans ce cas, nous invoquons le délégué auquel se réfère l'option Method mais ce code pourrait aussi représenter un appel à une méthode appelée "Method". C'est déroutant.

2voto

mike z Points 14365

Si toutes les méthodes partagent la même signature, une solution serait de mettre en cache un délégué :

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

2voto

Sergey Berezovskiy Points 102044

Pour ma part, il est beaucoup plus facile de prendre en charge un simple interrupteur que de s'occuper de la réflexion, d'un tableau de noms de méthodes ou de délégués, et d'invoquer ces éléments :

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

1voto

Justin Pihony Points 21088

Oui, ce dont vous parlez est réflexion . Voici un article sur la façon d'invoquer une méthode . Il y a beaucoup de choses que vous pouvez trouver sur la réflexion en utilisant google.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X