我必须找到一种方法,用它的真实值替换 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);
检查委托(delegate)时,您可以看到:
{t => t.SubObjs.get_Item(value(testExpression.Program+<>c__DisplayClass4).i).TestSTR}
在for循环外调用delegate时,“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发布
最佳答案
只需获取 Member
表达式中的属性并查看它是否是 FieldInfo
...
如果您只希望它用于类是编译器生成的情况,您可以使用
if (expression.Member is FieldInfo &&
expression.Member
.DeclaringType
.IsDefined(typeof(CompilerGeneratedAttribute), false))
{
....
}
编译器生成类型可能还有其他原因。我觉得这不是个好主意。
难道你就不能避免在 lambda 表达式中捕获循环变量吗?
关于c# - 如何识别类型为 "field reference"的 Lambda MemberExpression,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6635678/