【发布时间】:2011-07-09 15:27:08
【问题描述】:
我必须找到一种方法,将 lambda 表达式中的隐式字段引用替换为其实际值。例如:
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 节点是隐式字段引用???
提前致谢!!!
感谢this stakx 发帖
【问题讨论】:
-
“i”的值是唯一的问题吗?然后你可以简单地使用一个局部变量来让你的事情变得容易。
-
我不是唯一使用此代码的人,不幸的是我不能强迫开发人员使用我的库在他们的循环中创建局部变量...
-
没错,但我认为你的开发人员应该做对,如果你允许他们覆盖 c# 的默认行为,不会让他们感到困惑,即使它的编码方式错误,你的库也会使没错,他们会对不使用你的库的代码感到困惑。
-
@Akash 你是对的。我试图绕过默认的 c# 行为,以简化在循环中声明 lambda 的方式。
标签: c# .net lambda expression-trees