Присвойте значение параметру метода

Представьте себе метод со следующей подписью:

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

Значение в data должен быть назначен либо A, B, C или ничего, в зависимости от значения id, Короче если id == "A" затем A = data;

Проблема в том, что тело этого метода набрано человеком, но подпись генерируется во время выполнения. Из-за этого невозможно жестко закодировать логику, потому что во время разработки неизвестно, сколько будет параметров ref и как они называются. Этот кусок кода может быть вставлен в любое количество методов, каждый из которых может иметь свою подпись, и он должен работать в каждом из них.

Я знаю, как получить все параметры метода, в котором находится в данный момент, но я не могу понять, как присвоить значение одному из этих параметров. Я ищу что-то вроде следующего:

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

1 ответ

Решение

Вы не можете получить доступ к параметрам по имени, так как вы не можете использовать отражение переменных / параметров. У вас могут быть некоторые варианты, если это был IL, но не совсем в C#. Мой совет: измените API, возможно, что-то, включающее либо массив, либо (возможно, лучше) словарь. Рассматривать:

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

Не уверен, поможет ли это... но то, что вы пытаетесь сделать, не очень благоприятно для размышлений. Другой вариант - генерировать этот метод динамически, либо как часть вашего процесса сборки, либо через IL. Либо должно быть в порядке. Таким образом, он может генерировать (как C# или (во время выполнения) 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 */
    }
}

Дополнительный подход: типизированный объект: скажем, у вас есть:

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

где obj является объектом со свойствами, такими как "A", "B", "C"; то, что вы пытаетесь сгенерировать, это:

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

что, конечно, можно сделать с помощью отражения:

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

или если производительность критична, что-то вроде fast-member:

var wrapped = ObjectAccessor.Create(obj); 
wrapped[id] = data;
Другие вопросы по тегам