2013-04-25 5 views
30

プロパティの名前から実行時にネストされたプロパティのラムダ式を作成しようとしています。しかし、私は与えられていますすべてがFooの種類や文字列"myBar.name"文字列からネストされたプロパティのLambdaExpressionを構築する

それであればある

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

:クラスで

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

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

:基本的に私はで指定されたラムダ式を作成しようとしています値が"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")) 

しかし、私はそれがすべての作業、または実行時にこれを行うには良い方法があるかどう取得する方法を考え出すように見えることはできません。

答えて

62

あなたが意味するか:たとえば

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 
} 

+0

これはまさに私が探していたものです。私の間違いは、ネストされたプロパティを取得する前に(Callを使って)ボディ式を呼び出す必要があると考えていたことです。 – Seph

+0

すばらしい答え! +1を明確にする – ps2goat

+0

私のために解決したMarc Gravellからのすばらしい答え。ボーナスとして、resharperはあなたのコードにこれを行いました: var param = Expression.Parameter(type、 "x"); 式body = propertyName.Split( '。')。集計(param、Expression.PropertyOrField); return Expression.Lambda(body、param); –

関連する問題