Мне пришлось найти способ замены неявных ссылок на поля в лямбда-выражении его действительным значением. Например:
Expression<Func<TestObject, String>> exp = null;
for (int i = 0; i < 1; i++)
{
exp = t => t.SubObjs[i].TestSTR;
}
Func<TestObject, String> testFunc = exp.Compile();
String testValue = testFunc(myObj);
Осматривая делегата, вы можете увидеть это:
{t => t.SubObjs.get_Item(value(testExpression.Program+<>c__DisplayClass4).i).TestSTR}
При вызове делегата вне цикла for значение «i» определяется по ссылке. Но «i» изменилось с момента последней итерации («i» == 1, а не 0).
Итак, я строю определенный ExpressionVisitor, чтобы заменить соответствующий узел на ConstantExpression:
public class ExpressionParameterSolver : ExpressionVisitor
{
protected override Expression VisitMember(MemberExpression node)
{
if (node.ToString().StartsWith("value(") && node.NodeType == ExpressionType.MemberAccess)
{
var index = Expression.Lambda(node).Compile().DynamicInvoke(null);
return Expression.Constant(index, index.GetType());
}
return base.VisitMember(node);
}
}
Я не нашел другого способа, кроме .StartsWith ("value ("), чтобы определить, что текущий узел является ссылкой на поле ... этот тип узла наследуется от FieldExpression, но этот класс является внутренним и я не уверен, что FieldExpression инкапсулирует только то, что я считаю «неявной ссылкой на поле».
Так есть ли способ (атрибут или метод) явно знать, что узел MemberExpression является неявной ссылкой на поле ???
Заранее спасибо !!!
и благодаря этой записи 1020 *