2016-03-30 50 views
4

Basicaly我希望做的是:添加的LINQ where條件泛型IQueryable <T>

var validValues = new List<int>() { 1, 2, 34 }; 

query = query.Where(item => validValues.Contains(item.Value)); 

只是我不知道它是什麼類型,我想做到這一點作爲一個擴展方法:

public static IQueryable<T> Where<T>(this IQueryable<T> source, string propertyName, IList<int> accpetedValues) 
{ 
    if (accpetedValues == null || !accpetedValues.Any() || string.IsNullOrEmpty(propertyName)) 
     return source; 

    // HERE 

    return source; 
} 

我發現這個職位IQueryable Extension: create lambda expression for querying a column for a keyword 但它不是我想要的,我無法弄清楚如何使其適應我的情況......

+0

你到底想達到什麼目的?你想過濾出有效的值嗎?因爲你是'Where'擴展名返回項目。 – vendettamit

+0

嘗試將where條件添加到IQueryable中 – JCorriveau

+0

我想保留數據,其中某個屬性值包含在有效值中 – JCorriveau

回答

0

這裏有一個更好的版本,其中與通用有效值集合動態表情:

public static IQueryable<Tsource> Where<Tsource, Tproperty>(this IQueryable<Tsource> source, Expression<Func<Tsource, Tproperty>> property, IList<int> accpetedValues) 
    { 
     var propertyName = ((MemberExpression)property.Body).Member.Name; 

     if (accpetedValues == null || !accpetedValues.Any() || string.IsNullOrEmpty(propertyName)) 
      return source; 

     var item = Expression.Parameter(typeof(Tsource), "item"); 
     var selector = Expression.PropertyOrField(item, propertyName); 
     var predicate = Expression.Lambda<Func<Tsource, bool>>(
      Expression.Call(typeof(Enumerable), "Contains", new[] { typeof(Tproperty) }, 
       Expression.Constant(accpetedValues), selector), 
      item); 
     return source.Where(predicate); 
    } 

用法:

query = query.Where(item => item.Value, validValues)); 
+0

除了如果我的屬性的類型爲int,這是行得通的嗎?和我接受的值列表是類型列表,我得到一個錯誤,我會檢查如何解決它 – JCorriveau

1

這是類似鏈接職位,但這個時候就需要使用Expression.Call調用Enumerable.Contains<int>這樣的動態構建Expression<Func<T, bool>>

public static IQueryable<T> Where<T>(this IQueryable<T> source, string propertyName, IList<int> accpetedValues) 
{ 
    if (accpetedValues == null || !accpetedValues.Any() || string.IsNullOrEmpty(propertyName)) 
     return source; 

    var item = Expression.Parameter(typeof(T), "item"); 
    var selector = Expression.PropertyOrField(item, propertyName); 
    var predicate = Expression.Lambda<Func<T, bool>>(
     Expression.Call(typeof(Enumerable), "Contains", new[] { typeof(int) }, 
      Expression.Constant(accpetedValues), selector), 
     item); 
    return source.Where(predicate); 
} 
0

如果你把它與任意集合(不僅僅是IList的)工作 - 你可以不喜歡它這個:

static class Extensions { 
    public static IQueryable<TEntity> WhereContains<TEntity, TProperty>(this IQueryable<TEntity> source, IList<TProperty> accpetedValues, Expression<Func<TEntity, TProperty>> property) { 
     if (accpetedValues == null || !accpetedValues.Any()) 
      return source; 

     var member = property.Body as MemberExpression; 
     if (member == null) 
      return source; // better throw 

     string propertyName = member.Member.Name; 
     var containsMethod = typeof (ICollection<TProperty>).GetMethod("Contains"); // get Contains method of IList 
     var parameter = Expression.Parameter(typeof (TEntity), "p"); 
     var memberAccess = Expression.Property(parameter, propertyName); // p.ValidValue (for example) 
     var list = Expression.Constant(accpetedValues); // your list 
     var body = Expression.Call(list, containsMethod, memberAccess); // list.Contains(p.ValidValue) 
     return source.Where(Expression.Lambda<Func<TEntity, bool>>(body, parameter)); 
    } 
} 

注意我也使用屬性訪問表達式而不是傳遞屬性名稱作爲字符串 - 這是更安全的類型。使用這樣的:

var validValues = new List<int>() { 1, 2, 34 }; 
query = query.WhereContains(validValues, item => item.ValidValue);