Присвойте значение параметру метода - PullRequest
3 голосов
/ 29 февраля 2012

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

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 Ответ

2 голосов
/ 29 февраля 2012

Вы не можете получить доступ к параметрам по имени, так как вы не можете реально использовать отражение переменных / параметров.У вас могут быть некоторые варианты, если это был 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;
...