Вопрос

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

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;
    }
  }
}
Это было полезно?

Решение

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

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

или если производительность имеет решающее значение, что-то вроде быстрый участник:

var wrapped = ObjectAccessor.Create(obj); 
wrapped[id] = data;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top