Atribuir valor para o parâmetro do método
-
14-11-2019 - |
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;
}
}
}
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;