【问题标题】:Construct LambdaExpression for nested property from string从字符串构造嵌套属性的 LambdaExpression
【发布时间】:2013-04-25 06:51:59
【问题描述】:

我正在尝试在运行时根据属性名称为嵌套属性创建 lambda 表达式。基本上我正在尝试创建由以下指定的 lambda 表达式:

var expression = CreateExpression<Foo, object>(foo => foo.myBar.name);

private static Expression CreateExpression<TEntity, TReturn>(Expression<Func<TEntity, TReturn>> expression)
{
    return (expression as Expression);
}

类:

class Foo
{
    public Bar myBar { get; set; }
}
class Bar
{
    public string name { get; set; }
}

但是我得到的只是Foo 的类型和字符串"myBar.name"

如果它是一个普通属性,例如只需要值 "myBar",那么我可以使用以下内容:

private static LambdaExpression GetPropertyAccessLambda(Type type, string propertyName)
{
    ParameterExpression odataItParameter = Expression.Parameter(type, "$it");
    MemberExpression propertyAccess = Expression.Property(odataItParameter, propertyName);
    return Expression.Lambda(propertyAccess, odataItParameter);
}

但是,此代码不适用于嵌套属性,我不确定如何创建 LambdaExpression 来完成 foo.myBar.name 的工作。

我认为它会是这样的:

GetExpression(Expression.Call(GetExpression(Foo, "myBar"), "name"))

但我似乎无法弄清楚如何让它全部工作,或者是否有更好的方法可以在运行时做到这一点。

【问题讨论】:

    标签: c# .net linq lambda expression-trees


    【解决方案1】:

    你的意思是:

    static LambdaExpression CreateExpression(Type type, string propertyName) {
        var param = Expression.Parameter(type, "x");
        Expression body = param;
        foreach (var member in propertyName.Split('.')) {
            body = Expression.PropertyOrField(body, member);
        }
        return Expression.Lambda(body, param);
    }
    

    例如:

    class Foo {
        public Bar myBar { get; set; }
    }
    class Bar {
        public string name { get; set; }
    }
    static void Main() {
        var expression = CreateExpression(typeof(Foo), "myBar.name");
        // x => x.myBar.name
    }
    

    ?

    【讨论】:

    • 是的,这正是我想要的,我的错误是认为我需要在获取嵌套属性之前调用正文表达式(使用 Call)。
    • 很好的答案!为清楚起见 +1
    • Marc Gravell 的精彩回答为我解决了这个问题。作为奖励,resharper 对您的代码执行此操作: var param = Expression.Parameter(type, "x");表达式主体 = propertyName.Split('.').Aggregate(param, Expression.PropertyOrField); return Expression.Lambda(body, param);
    • 真的很酷。马克,有没有办法对嵌套列表使用相同的行为?我的意思是 class Foo {public List myBar { get;放; }}
    【解决方案2】:

    要构造一个 lambda 表达式,但您可以使用内联解决方案:

    var param = Expression.Parameter(typeOf(FooBar), "x");
    
    // you "concat" your expression here :
    var propertyExpression = Expression.PropertyOrField(param, "myBar");
    propertyExpression = Expression.PropertyOrField(propertyExpression, "name");
    // expected result : "x.myBar.name" as a body expression
    
    var expression = Expression.Lambda(propertyExpression, param);
    // x => x.myBar.name
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-31
      • 2017-10-25
      • 2019-07-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多