式に式を<のFunc >変換する方法のC#<のFunc >
-
19-08-2019 - |
質問
私は前にラムダに基づいてC#の式を使用しているが、私は手でそれらを構成する経験がありません。 Expression<Func<SomeType, bool>> originalPredicate
を考えると、私が作成したいExpression<Func<OtherType, bool>> translatedPredicate
。
この場合SomeTypeとOtherTypeは同じフィールドを持っているが、それらは(共通インタフェースに基づいた継承としない)関連しないれます。
背景:私はSQLにLINQに基づいて、リポジトリの実装を持っています。私はPOCOで私のモデルを維持するために、私のモデルエンティティへのSQLエンティティにLINQを投影します。私は(仕様書の形式など)リポジトリに式を渡したいが、彼らはモデルエンティティに基づくべきです。それはSQLエンティティへのLINQに基づいた表現を期待するのでしかし、私は、データコンテキストにそれらの表現を渡すことはできません。
解決
Expression
では、最も簡単な方法は、変換の表現のである。
class Foo {
public int Value { get; set; }
}
class Bar {
public int Value { get; set; }
}
static class Program {
static void Main() {
Expression<Func<Foo, bool>> predicate =
x => x.Value % 2 == 0;
Expression<Func<Bar, Foo>> convert =
bar => new Foo { Value = bar.Value };
var param = Expression.Parameter(typeof(Bar), "bar");
var body = Expression.Invoke(predicate,
Expression.Invoke(convert, param));
var lambda = Expression.Lambda<Func<Bar, bool>>(body, param);
// test with LINQ-to-Objects for simplicity
var func = lambda.Compile();
bool withOdd = func(new Bar { Value = 7 }),
withEven = func(new Bar { Value = 12 });
}
}
これは異なるプロバイダによって異なってサポートされることに注意してください。 EFは、LINQツーSQLがない場合でも、例えば、それを好きではないかもしれません。
他のオプションは、対応するメンバーを見つけるためにリフレクションを使用して、の完全にの式ツリーを再構築することです。はるかに複雑ます。
他のヒント
また、あなたのオリジナルのデリゲートをラップ含み、私が発見した一つの他の方法、あります。
Func<T, object> ExpressionConversion<U>(Expression<Func<T, U>> expression)
{
Expression<Func<T, object>> g = obj => expression.Compile().Invoke(obj);
return g.Compile();
}
翻訳を行うには、暗黙的な方法はありません。あなたは、引数の型から新しい型を作成し、ラムダの内側に、既存のデリゲートをラップする必要があります:
var translatedPredicate = x => originalPredicate(OtherTypeFromSomeType(x))
OtherTypeFromSomeType
がOtherType
引数からSomeType
インスタンスを作成する場所ます。
私はあなたと同じ問題を持っていたと私はEFでこのようにそれを修正します:
var viewModeValue = dbContext.Model.Select(m => new ViewModel{Field = m.Field}).Where(predicate) //predicate is an Expression<Func<ViewModel, bool>>
Entity Frameworkのは、正しいSQLコマンドを構築する方法を知っています。式を変換すると、不変のように構築されているので、はるかに複雑であり、あなたが何か間違ったことをすれば望ましくない実行時の影響を引き起こす可能性があり、そして、私の場合には、少なくとも、それが必要とされていません。