2011-02-25 36 views
2

我正在做一些使用反射的工作,並希望創建一個LambdaExpression,我可以針對List<T>集合運行並與HashSet<int>集合相交以找到任何匹配。編譯Lambda表達式時參數不在範圍中

我的問題是,T沒有實現一個通用的基類或接口,因此類型和需求tp的反射以編程方式構建Lambda表達式。

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},請將idList替換爲Expression.Constant

請注意,如果您想獲得性能,則需要使用鍵入,而不是DynamicInvoke

+0

哇,你很快!我打算明天登錄,看看有沒有人回覆:) – mnield

+0

那麼,那將是另一個ParameterExpression呢,對吧?確實,在最終版本中並不是一個常數。 – mnield

+0

@mnield - 你已經有了參數表達式;你只是沒有把它包含在對'Lambda'的調用中。它應該是'Expression.Lambda(methodCall,objectListParam,idList)'(或其他方式);同樣,您需要傳入* actual *列表來調用:'.DynamicInvoke(entityList,idList)' –

相關問題