2016-12-18 6 views
3

私は式Expression<Func<TFoo, string>> expをとる方法があります。同じ型の2つの式をマージする(ブールなし)

私はこの

MyMethod(o => o.SomeStringProperty); 

のような単一の式を渡すことができます。しかし、今、私は(2つの文字列のプロパティから)式を結合し、私が見つけた他のすべての例では、Expression<Func<Foo, bool>>であり、この方法

に渡したいです。

私は

Expression<Func<TFoo, string>> fn1 = x => x.SomeStringProperty1; 
Expression<Func<TFoo, string>> fn2 = x => x.SomeStringProperty2; 

var body = Expression.Coalesce(fn1.Body, fn2.Body); 
var lambda = Expression.Lambda<Func<TFoo, string>>(body, fn1.Parameters[0]); 

を試みたが、ほとんどの式のすべての機能は、例外がスローされます。これをどのように組み合わせるか?

+0

よう

public static class ExpressionUtils { public static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target) { return new ParameterReplacer { Source = source, Target = target }.Visit(expression); } class ParameterReplacer : ExpressionVisitor { public ParameterExpression Source; public Expression Target; protected override Expression VisitParameter(ParameterExpression node) { return node == Source ? Target : base.VisitParameter(node); } } } 

あなたは「組み合わせ」とはどういう意味ですか:

第二のアプローチは、最初のラムダ式のパラメータに二ラムダ式本体を再バインドするための単純なパラメータ代替ヘルパーを使用しています2つの表現?あなたの例では、2つの引数を持つメソッドを呼び出すだけです。 –

+1

@IvanStoev:私の質問を更新しました –

答えて

1

ラムダ式を組み合わせる場合、ラムダ式にバインドされていることと、結果の式で同じパラメータインスタンスが使用されていることを確認する必要があります。

これは2つの方法で実現できます。

最初はExpression.Invokeメソッドを使用することです:

var body = Expression.Coalesce(fn1.Body, Expression.Invoke(fn2, fn1.Parameters[0])); 
var lambda = Expression.Lambda<Func<TFoo, string>>(body, fn1.Parameters[0]); 

をこれが最も簡単な方法ですが、呼出し式をサポートしていないエンティティフレームワークと同様のため、サポートされていない表現を作成します。この

var body = Expression.Coalesce(fn1.Body, 
    fn2.Body.ReplaceParameter(fn2.Parameters[0], fn1.Parameters[0])); 
var lambda = Expression.Lambda<Func<TFoo, string>>(body, fn1.Parameters[0]); 
関連する問題