Присвойте значение параметру метода
-
14-11-2019 - |
Вопрос
Представьте себе метод со следующей сигнатурой:
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;