Question

Imaginez une méthode avec la signature suivante:

public void ExampleMethod(string id, object data, 
                          ref object A, ref object B, ref object C)
{
  //...
}

La valeur dans data doit être affecté à soit A, B, C ou rien, selon la valeur de id. Bref, si id == "A" alors A = data;

Le problème est que le corps de cette méthode est tapé par un humain mais la signature est générée au moment de l'exécution. Pour cette raison, il n'est pas possible de coder dur la logique car il est inconnu au moment de la conception du nombre de paramètres de réf. Il y aura et comment ils sont appelés. Ce morceau de code peut être inséré dans n'importe quel nombre de méthodes, chacun potentiellement avec une signature différente, et il doit fonctionner dans chacun.

Je sais comment obtenir tous les paramètres de la méthode dans laquelle on se trouve actuellement, mais je ne peux pas comprendre comment attribuer une valeur à l'un de ces paramètres. Ce que je recherche, c'est quelque chose comme celui qui suit:

public void ExampleMethod(string id, object data, 
                          ref object A, ???????, ref object Z)
{
  MethodBase method = MethodBase.GetCurrentMethod();
  foreach (ParameterInfo parameter in method.GetParameters())
  { 
    if (id == parameter.Name)
    {
      // Problem: assign data to parameter.
      return;
    }
  }
}
Était-ce utile?

La solution

Vous ne pouvez pas accéder aux paramètres par nom, car vous ne pouvez pas vraiment utiliser la réflexion sur les variables / paramètres. Vous pourriez avoir des options si c'était IL, mais pas vraiment en C #. Mon conseil serait: changer l'API, peut-être quelque chose impliquant soit un tableau ou (peut-être mieux) un dictionnaire. Envisager:

public void ExampleMethod(string id, object data,
        IDictionary<string,object> args) {
    args[id] = data;
}

Je ne sais pas si cela aide ... mais ce que vous essayez de faire n'est pas vraiment adapté à la réflexion. L'autre option consiste à générer cette méthode dynamiquement, soit dans le cadre de votre processus de construction, soit via IL. L'un ou l'autre devrait être bien. Il pourrait donc essentiellement générer (comme C # ou (au moment de l'exécution) IL):

public void ExampleMethod(string id, object data, 
                          ref object A, ref object B, ref object C)
{
    switch(id) {
        case "A": A = data; break;
        case "B": B = data; break;
        case "C": C = data; break;
        default: /* do something */
    }
}

Une approche supplémentaire: l'objet dactylographié: disons que vous avez:

public void ExampleMethod(string id, object data, SomeType obj) {...}

obj est un objet avec des propriétés telles que "A", "B", "C"; alors ce que vous essayez de générer est:

switch(id) {
    case "A": obj.A = data; break;
    case "B": obj.B = data; break;
    case "C": obj.C = data; break;
    default: /* do something */
}

Ce qui peut bien sûr être fait avec réflexion:

var prop = obj.GetType().GetProperty(id);
prop.SetValue(obj, data, null);

ou si les performances sont essentielles, quelque chose comme membre rapide:

var wrapped = ObjectAccessor.Create(obj); 
wrapped[id] = data;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top