从string构造用于嵌套属性的LambdaExpression

时间:2013-04-25 06:51:59

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

我正在尝试从属性名称在运行时为嵌套属性创建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"))

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

2 个答案:

答案 0 :(得分:86)

你的意思是:

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
}

答案 1 :(得分:0)

要构建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