Pergunta

Imagine um método com a seguinte assinatura:

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

O valor em data precisa ser atribuída a um A, B, C ou nada, dependendo do valor de id.Em suma, se id == "A" em seguida, A = data;

O problema é que o corpo desse método é escrito por um ser humano, mas a assinatura é gerada em tempo de execução.Devido a isso, não é possível codificar a lógica, porque ele é desconhecido no tempo de design como muitos parâmetros ref lá vai ser e o que eles são chamados.Este pedaço de código pode ser inserido em qualquer número de métodos, cada potencialmente com uma assinatura diferente, e ele tem que funcionar em todos e cada um.

Eu sei como obter todos os parâmetros do método é atualmente, mas eu não consigo descobrir como atribuir um valor a um desses parâmetros.O que eu estou procurando é algo como o seguinte:

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;
    }
  }
}
Foi útil?

Solução

Você não pode parâmetros de acesso por nome, mas você não pode realmente usar a reflexão sobre variáveis/parâmetros.Você pode ter algumas opções, se este foi IL, mas, na verdade, não C#.Meu conselho seria:alterar a API, talvez algo envolvendo uma matriz ou (talvez o melhor) um dicionário.Considere:

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

Não tenho certeza se isso ajuda...mas o que você está tentando fazer não é realmente de reflexão-friendly.A outra opção é gerar este método de forma dinâmica, seja como parte do processo de compilação, ou através de IL.Ou deve ser fino.Assim, poderia, essencialmente, gerar (como C# ou (em tempo de execução) O):

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

Um adicional de abordagem:o tipo de objeto:digamos que você tenha:

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

onde obj é um objeto com propriedades tais como "A", "B", "C";então, o que você está tentando gerar é:

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

o que pode ser feito com reflexão:

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

ou se o desempenho é crítico, algo como rápido-membro:

var wrapped = ObjectAccessor.Create(obj); 
wrapped[id] = data;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top