2012-02-21 10 views
31

私のコードにFunc<TCollection, T>があります。私はそれを使用して特定のプロパティを選択します。Funcから式を作成

別のメソッドへの呼び出しでは、パラメータとしてExpression<Func<TCollection, T>>が必要です。

Func<TCollection, T>からExpression<Func<TCollection, T>>に変換する方法はありますか?

おかげ

答えて

30

式は、元の文ではなく、ILを知っている必要があるので、あなたは法に基づいて式を再作成することはできません。あなたはだけで式ツリーを作成することもできますがEFのようなシステムは本当にこの

+2

ILを入手できるとすれば、リフレクタとILSpyはILを逆コンパイルできます。 (もちろん、ILがコンパイルされたコードとまったく同じであるという保証はありません)。デリゲートのILにアクセスする方法はありますか? – phoog

+5

私はあなたの呼び出しでfunc.Targetを追加する必要があるかもしれないと思います。 私はより複雑なFunc <>でこれを試しました、そして、私はヌルオブジェクトでインスタンスメソッドを呼び出そうとしていると不平を言った。 私はそれをExpression.Call(Expression.Constant(func.Target)、func.Method、args)に変更しました。すべては問題ありませんでした。 – ben

25

では動作しないことをしかし

Func<int> func =() => 1; 
Expression<Func<int>> expression = Expression.Lambda<Func<int>>(Expression.Call(func.Method)); 

注:ただしのようなあなたのFUNCにメソッドの呼び出しを行うExpressonを作成することができますなぜなら、デリゲートを呼び出すコードは、表現ツリーを分析するコードに関しては、基本的にはブラックボックスになるからです。 LINQ to SQLのようなものを使用しようとしていると仮定すると、クエリアナライザはSQLに変換するためにロジックに仲間入りできる必要があります。プレーンデリゲートに達すると、それを実行できません。

代理人が最初に出てくるコードを変更して、代わりに式ツリーを作成する必要があります。

7

あなたはこのような何か行うことができます。

Func<object, string> func = a => a.ToString(); 
Expression<Func<object, string>> expr = a => func(a); 

をしかし、あなただけのオリジナルのFuncにあなたのメソッドの呼び出しを含む式を取得します。 func自体の包含を分析することはできません。

+4

しかし、当然ながら、Skeet氏は私よりもはるかに優れています! :-) – Simon

9

デリゲート(Func<TCollection, T>Expression<Func<TCollection, T>>)から式を作成することはできませんが、opositeを実行できます。

つまり、Expression<Func<TCollection, T>>Func<TCollection, T>に変換します(.compile)。

これらの両方が必要な場合は、関数で式を使用できます。必要な場合は、指定されたコレクションオブジェクトで式をコンパイルして実行できます。

もちろん、式のコンパイルが遅いことに注意してください。

+0

ありがとう、私を救った;( – Akbari

+0

これはちょうど私が必要としたものです。ちょうど重複したコードを減らそうとしていました。 –

関連する問題