2014-06-26 122 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