2014-06-26 77 views
1

我想知道如何動態地傳遞一個對象的屬性作爲將在Where方法IQueryable中使用的lambda的一部分。linq的Where方法的動態lambda

假設我有這樣的代碼:

var list = new List<Item>(); 
... 

var filtered = list.AsQueryable().Where(x => x.SomePropertyA.Contains(someStringValue)); 

我的任務就是讓最後一條語句作爲一種通用的方法和使用參數:

IQueryable<Item> SomeMethod(Expression<Func<Item, string>> expr, string stringValue) { 

    return list.AsQueryable().Where (???); 
} 

SomeMethod(x => x.SomePropertyA, someStringValue); 
SomeMethod(x => x.SomePropertyB, someStringValue); 

...

我的膽量告訴我,我將不得不使用表達式類來調用由expr返回的字符串的Contains方法,但不知道如何做到這一點,因爲我不是很famic騙子用這種...

+1

在運行時你選擇什麼屬性來傳遞方法? – terrybozzio

+0

該方法將用於多個地方,具有不同的對象和不同的屬性。其任務是儘可能使方法儘可能通用。 – Vlad

+0

您可以使用[Reflection](http://msdn.microsoft.com/zh-cn/library/ms173183.aspx)獲取您想要的屬性 – Caleb

回答

1

此方法將創建所需的表達式:

static Expression<Func<T, bool>> CreateContainsPredicate<T>(Expression<Func<T, string>> property, string value) 
{ 
    return Expression.Lambda<Func<T, bool>>(// Where() wants this kind of expression 
     Expression.Call(     // we need to call method 
      property.Body,     // on instance returned by passed expression 
      typeof(string).GetMethod("Contains", new [] { typeof(string) }), // call 'Contains()' 
      Expression.Constant(value)),  // pass value to Contains() method 
     property.Parameters);    // resulting expression has same parameters as input expression 
} 

用法:

IQueryable<Item> SomeMethod(Expression<Func<Item, string>> expr, string stringValue) { 
    return list.AsQueryable().Where(CreateContainsPredicate<Item>(expr, stringValue)); 
} 
+0

非常棒,正是我需要的! – Vlad