2012-06-14 44 views
6

Tôi có một tình huống mà tôi cần phải tự động xây dựng một danh sách các bộ lọc để áp dụng cho một danh sách các đối tượng. Những đối tượng đó có thể là bất cứ thứ gì thực hiện một giao diện chứa tất cả các thuộc tính mà tôi cần để lọc.Ràng buộc chung C# không hoạt động như mong đợi

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

public class SomeStuff : IStuff 
{ 
    ... 
} 

public class SomeOtherStuff : IStuff 
{ 
    ... 
} 

Tôi có một danh sách các tiêu chí được xác định như vậy ...

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

và thêm các tiêu chí như vậy ...

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

Sau đó tôi áp dụng các tiêu chí cho truy vấn của tôi như vậy ...

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

trong đó sử dụng phương pháp mở rộng sau ...

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; 
} 

Trình biên dịch là nói cho tôi ...

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

Khi tôi di chuột qua đường màu đỏ dưới sự sai sót trong IDE nói rằng nó không thể giải quyết phương thức giữa

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 

Nếu tôi thử truyền biểu thức đến Expression<Func<T, bool>>, nên hoạt động khi T bị ràng buộc để triển khai giao diện IStuff. Tôi nhận được

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

EDIT Nhờ câu trả lời Raphaël 's Tôi cố định phương pháp mở rộng và cuối cùng tìm thấy vấn đề thực sự tôi đã có, đó là một vấn đề đúc khi tôi đã gọi mã. Dễ dàng sửa bằng cách thêm .Cast<SomeStuff>() sau cuộc gọi ApplyCriteria.

Trước

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

Sau

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

Trả lời

7

thay đổi thứ hai loại tham số để List<Expression<Func<T,bool>>> (T thay vì 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; 
} 

và phương pháp của bạn có thể được (thx reshar mỗi), được viết lại thành

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 để có câu trả lời đúng và tưởng tượng +1 cho đề xuất cải thiện. – SimpleVar

+0

cảm ơn. Tôi đã thử nó và đã có các lỗi khác, mà bây giờ tôi đã tìm thấy một giải pháp. Tôi sẽ cập nhật các câu hỏi với các chi tiết. –

Các vấn đề liên quan