代码之家  ›  专栏  ›  技术社区  ›  Seph

从字符串构造嵌套属性的LambdaExpression

  •  52
  • Seph  · 技术社区  · 11 年前

    我正试图在运行时根据属性的名称为嵌套属性创建一个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"))
    

    但我似乎不知道如何让这一切正常工作,或者是否有更好的方法在运行时做到这一点。

    3 回复  |  直到 10 年前
        1
  •  139
  •   Marc Gravell    11 年前

    你的意思是:

    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
    }
    

    ?

        2
  •  0
  •   Zoidbergseasharp    2 年前

    对于这种方法, propertyPath "Car", "Colour" 对于 Driver.Car.Colour .

    
    public static MemberExpression NestedProperty(Expression propertyHolder, params string[] propertyPath)
    {
        MemberExpression memberExpression = Expression.Property(propertyHolder, propertyPath[0]);
    
        foreach (var member in propertyPath.Skip(1))
        {
            memberExpression = Expression.Property(memberExpression, member);
        }
    
        return memberExpression;
    }
    
        3
  •  -1
  •   Moff452    4 年前

    要使用内联解决方案构造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