2011-02-25 8 views
2

私はリフレクションを使用して少し作業をしており、List<T>コレクションに対して実行できるLambdaExpressionを作成し、一致するものを見つけるためにHashSet<int>コレクションと交差します。パラメータがLambdaExpressionをコンパイルするときに範囲外

私の問題は、Tは共通の基底クラスまたはインターフェイスを実装していないため、型と要件tpの反映によってプログラムでラムダ式が構築されていることです。

I'fは、私は自分のタイプを知っていた、私が実行するwnatことです:

List<TestClass> entityList = GetOriginalList(); 
HashSet<int> idList = new HashSet<int>() { 1, 2, 3, 4 }; 
List<TestClass> filteredList = entityList.Where(o => idList.Contains(o.Id)).ToList(); 

私はLambdaExpressionを使ってこれを行う方法をあざける始めたが、私はコンパイルするものを取得することができないことができますそれが何をしたいのかを理解しているようです(つまり、HashSet<int>の変数を入力してください)。私の身体的な試みは以下の通りです。LambdaExpressionをコンパイルする方法と、もう一方の端にあるList<myObject>を実際にどのように実行するのかについての提案はありますか?

using System; 
using System.Collections.Generic; 
using System.Linq.Expressions; 
using System.Reflection; 

namespace PoCDynamicLambda 
{ 
    class Program 
    { 
     class TestClass 
     { 
      private int _id; 
      private string _value; 

      public int Id { get { return this._id; } set { this._id = value; } } 
      public string Value { get { return this._value; } set { this._value = value; } } 

      public TestClass(int id, string value) 
      { 
       this._id = id; 
       this._value = value; 
      } 
     } 

     static void Main(string[] args) 
     { 
      List<TestClass> entityList = new List<TestClass>() 
      { 
       new TestClass(1, "One"), 
       new TestClass(2, "Two"), 
       new TestClass(3, "Three") 
      }; 

      HashSet<int> idList = new HashSet<int>() { 2, 3, 5 }; 

      MethodInfo containsMethod = idList.GetType().GetMethod("Contains"); 
      ParameterExpression idListParam = Expression.Parameter(idList.GetType(), "idList"); 
      ParameterExpression objectListParam = Expression.Parameter(typeof(TestClass), "entityList"); 
      PropertyInfo idProperty = typeof(TestClass).GetProperty("Id"); 
      MemberExpression idMember = Expression.Property(objectListParam, idProperty); 
      MethodCallExpression methodCall = Expression.Call(idListParam, containsMethod, idMember); 
      LambdaExpression le = Expression.Lambda(methodCall, objectListParam); 
      Console.WriteLine(le); // returns {entityList => idList.Contains(entityList.Id)} 

      le.Compile(); // Error here 
      Console.WriteLine(le.Compile().DynamicInvoke(entityList)); 

      Console.ReadLine(); 
     } 

    } 
} 

ありがとうございます!

答えて

1

Expression.Lambdaへの呼び出しにidListを含める必要があります。最後の呼び出し(例ではDynamicInvoke)に引数を指定してください。または、{2,3,5}に固定する予定の場合は、idListExpression.Constantに置き換えます。

パフォーマンスを取得するには、と入力してと入力する必要があります(DynamicInvokeではなく)。

+0

うわー、あなたはすごいです!私は明日にログインして、誰かが答えたかどうかを見ています:) – mnield

+0

だから、それは別のParameterExpressionと同じでしょうか?確かに、最終版では一定ではありません。 – mnield

+0

@mnield - あなたはすでにパラメータ式を持っています。あなたはちょうど 'ラムダ 'の呼び出しにそれを含めなかった。これは 'Expression.Lambda(methodCall、objectListParam、idList)'(またはその逆)にする必要があります。同様に、呼び出すために*実際のリストを渡す必要があります: '.DynamicInvoke(entityList、idList)' –

関連する問題