Насколько я знаю, нет способа взаимодействия с ссылочными типами в деревьях выражений. (например, ничего не генерирует stind.*
или ldind.*
код операции).
Я работаю над переписчиком, чтобы обойти это раздражение. Поскольку я создаю новый тип, в котором тело метода заменено вызовами делегатов (чтобы обойти тот факт, что CompileToMethod
может выполнять только статические методы, которые не могут взаимодействовать с новыми членами). Что касается параметров by-ref и out, я решил заменить их использование на StrongBox<T>
.
Так что, если я наткнулся на метод, который имеет подпись, которая выглядит следующим образом: *
public class SomeClass
{
public virtual bool SomeMethod(string arg1,ref int arg2)
{
}
}
Переопределение, метод callbase и сгенерированное мной поле делегата будут выглядеть так:
public class SomeClass<1> : SomeClass
{
private static bool SomeMethod<0>(
SomeClass target,string arg1,StrongBox<int> arg2)
{
return call target.SomeMethod(arg1,ref arg2.Value)
}
private Func<SomeClass,string,StrongBox<int>,bool> <0>SomeMethod;
public override bool SomeMethod(string arg1,ref int arg2)
{
StrongBox<int> box = new StrongBox<int>();
box.Value = arg2;
bool retVal = <0>SomeMethod.Invoke(this,arg1,box);
arg2 = box.Value;
return retVal;
}
}
Тем не менее, для выполнения этого преобразования требуется довольно много кода, для каждого параметра это представляет большую сложность. Было бы намного проще, если бы я выполнил настройку box.Value = arg2
, если бы я мог сделать что-то вроде &box.Value = &arg2
, то есть присвоить его адрес адресу arg2 в его нынешнем виде. Таким образом, когда делегат выполняет мутацию в поле значения, изменения передаются. Это означает, что мне не нужно иметь переменную для хранения возвращаемого значения, и мне не нужно выполнять обновление эталонного значения.
В качестве альтернативы, если есть способ выполнить семантику присваивания по ссылке с деревьями выражений, я, конечно, все уши.