web-dev-qa-db-ja.com

文字列からネストされたプロパティのLambdaExpressionを構築します

プロパティの名前から実行時にネストされたプロパティのラムダ式を作成しようとしています。基本的に私はラムダ式を作成しようとしています:

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);
}

ただし、このコードはネストされたプロパティでは機能せず、foo.myBar.nameの機能を実行するためにLambdaExpressionを作成する方法がわかりません。

次のようなものになると思います。

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

しかし、それをすべて機能させる方法、または実行時にこれを行うより良い方法があるかどうか、私は理解できないようです。

38
Seph

もしかして:

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
}

100
Marc Gravell