如何识别“字段引用”类型的 Lambda MemberExpression
我必须找到一种方法,用 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 节点是一个隐式字段引用???
提前感谢
! >此 stakx 帖子
I have had to find a way to substitute implicit field references in a lambda expression with it's real value. For example :
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);
When inspecting the delegate, you can see this :
{t => t.SubObjs.get_Item(value(testExpression.Program+<>c__DisplayClass4).i).TestSTR}
When calling the delegate outside the for loop, the value of "i" is solved, by reference. But "i" have changed since it's last iteration ("i" == 1 and not 0).
So I build a specific ExpressionVisitor in order to replace the corresponding node with a 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);
}
}
I don't have found a way other than .StartsWith("value(") in order to detect that the current node is a reference to a field... this kind of node inherits from FieldExpression but this class is internal, and I'm not sure FieldExpression only encapsulate what I consider an "implicit field reference".
So is there a way (an attribute or a method) to explicitly know that a MemberExpression node is an implicit field reference ???
Thanks in advance !!!
and thanks to this stakx post
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
只需获取
Member
表达式中的 属性并查看它是否是FieldInfo
...如果您只希望它适用于该类是编译器生成的情况,您可以使用
可能还有其他原因不过,类型可能是编译器生成的。对我来说这听起来不是一个好主意。
难道一开始就不能避免在 lambda 表达式中捕获循环变量吗?
Just fetch the
Member
property from the expression and see whether it's aFieldInfo
...If you only want it to be for cases where the class is compiler-generated you could use
There can be other reasons why a type might be compiler-generated though. It doesn't sound like a terribly good idea to me.
Can't you just avoid capturing loop variables in your lambda expressions to start with?