2012-06-14 27 views
6

我有一種情況,我需要動態建立一個過濾器列表以應用於對象列表。這些對象可以是任何實現包含我需要過濾的所有屬性的接口。C#通用約束不能按預期工作

public interface IStuff 
{ 
    bool SuitableForSomething { get; set; } 
    bool SuitableForSomethingElse { get; set; } 
} 

public class SomeStuff : IStuff 
{ 
    ... 
} 

public class SomeOtherStuff : IStuff 
{ 
    ... 
} 

我有像這樣定義的標準列表...

public List<Expression<Func<IStuff, bool>>> Criteria { get; private set; } 

,並添加標準是這樣的...

Criteria.Add(x => x.SuitableForSomething); 
Criteria.Add(x => x.SuitableForSomethingElse); 

我然後應用標準我的查詢就像這樣...

var stuff= _stuffCache 
    .GetAll() 
    .AsQueryable() 
    .ApplyCriteria(Criteria); 

它使用以下的擴展方法...

public static IQueryable<T> ApplyCriteria<T>(this IQueryable<T> stuff, List<Expression<Func<IStuff, bool>>> criteria) 
    where T : IStuff 
{ 
    foreach (var expression in criteria) 
    { 
     stuff = Queryable.Where(stuff, expression); 
    } 
    return stuff; 
} 

編譯器告訴我...

cannot convert from 
    'System.Linq.Expressions.Expression<System.Func<IStuff,bool>>' 
to 
    'System.Linq.Expressions.Expression<System.Func<T,int,bool>>' 

當我將鼠標懸停在紅線錯誤下它說它無法解析IDE的方法

IQueryable<IStuff> Where<IStuff>(this IQueryable<IStuff>, Expression<Func<IStuff, bool>>) in class Queryable 
and 
    IQueryable<T> Where<T>(this IQueryable<T>, Expression<Func<T,int,bool>>) in class Queryable 

如果我嘗試將表達式轉換爲Expression<Func<T, bool>>,這應該適用於T被約束來實現IStuff接口。我得到

Cannot cast expression of type 'Expression<Func<IStuff, bool>>' to type 'Expression<Func<T, bool>>' 

編輯 由於Raphaël的答案,我固定的擴展方法,並最終找到了真正的問題,我有,這是一個鑄造問題,當我打電話的代碼。通過在撥打ApplyCriteria之後添加.Cast<SomeStuff>()即可輕鬆修復。

之前

var stuff= _stuffCache 
    .GetAll() 
    .AsQueryable() 
    .ApplyCriteria(Criteria); 

var stuff= _stuffCache 
    .GetAll() 
    .AsQueryable() 
    .ApplyCriteria(Criteria) 
    .Cast<SomeStuff>(); 

回答

7

改變第二參數類型List<Expression<Func<T,bool>>>(的Ť代替IStuff)

public static IQueryable<T> ApplyCriteria<T>(this IQueryable<T> stuff, List<Expression<Func<T, bool>>> criteria) 
    where T : IStuff 
{ 
    foreach (var expression in criteria) 
    { 
     stuff = Queryable.Where(stuff, expression); 
     //or stuff = stuff.Where(expression), as Where is an Extension method; 
    } 
    return stuff; 
} 

和你的方法可以是(THX reshar改寫爲

public static IQueryable<T> ApplyCriteria<T>(this IQueryable<T> stuff, List<Expression<Func<T, bool>>> criteria) 
      where T : IStuff 
     { 
      return criteria.Aggregate(stuff, (current, expression) => current.Where(expression)); 
     } 
+0

+1對於正確答案和虛構+1改善建議。 – SimpleVar

+0

謝謝。我已經嘗試過,並得到了其他錯誤,我現在已經找到了解決方案。我會用細節更新這個問題。 –