c# - 如何识别类型为 "field reference"的 Lambda MemberExpression

标签 c# .net lambda expression-trees

我必须找到一种方法,用它的真实值替换 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/

相关文章:

c# - LINQ 返回一个接口(interface)?

c# - Prism 7. 将 PrismApplication.CreateShell() 与非 Window 控件一起使用

c# - GetSection.Bind 在 .NET 4.7.2 中不起作用

c++ - 有没有办法将 lambda 表达式作为谓词模板参数传递?

c# - 如何将鼠标移动位置值存储在数组中?

.net - Windows UI 自动化无法识别按钮控件

.net - 用于检查系统要求和启动 .NET 应用程序的 native Windows 应用程序?

c# - EF 6.1 序列包含多个元素

node.js - 使用 nodeJS 调用 awscli

lambda - 如何在 C++0x 中重载用于组合函数的运算符?