Theo "Thiết kế ổ đĩa tên miền" của Eric Evan, bạn cần mẫu đặc điểm kỹ thuật. Một cái gì đó như thế này
public interface ISpecification<T>
{
bool Matches(T instance);
string GetSql();
}
public class ProductCategoryNameSpecification : ISpecification<Product>
{
readonly string CategoryName;
public ProductCategoryNameSpecification(string categoryName)
{
CategoryName = categoryName;
}
public bool Matches(Product instance)
{
return instance.Category.Name == CategoryName;
}
public string GetSql()
{
return "CategoryName like '" + { escaped CategoryName } + "'";
}
}
kho của bạn bây giờ có thể được gọi với thông số kỹ thuật
var specifications = new List<ISpecification<Product>>();
specifications.Add(
new ProductCategoryNameSpecification("Tops"));
specifications.Add(
new ProductColorSpecification("Blue"));
var products = ProductRepository.GetBySpecifications(specifications);
Bạn cũng có thể tạo ra một lớp CompositeSpecification chung chung mà sẽ chứa thông số kỹ thuật phụ và một chỉ số như mà logic điều hành để áp dụng cho họ VÀ/HOẶC
Tôi muốn có nhiều khuynh hướng kết hợp các biểu thức LINQ hơn.
Update - Ví dụ về LINQ trong thời gian chạy
var product = Expression.Parameter(typeof(Product), "product");
var categoryNameExpression = Expression.Equal(
Expression.Property(product, "CategoryName"),
Expression.Constant("Tops"));
Bạn có thể thêm một "và" như vậy
var colorExpression = Expression.Equal(
Expression.Property(product, "Color"),
Expression.Constant("Red"));
var andExpression = Expression.And(categoryNameExpression, colorExpression);
Cuối cùng, bạn có thể chuyển đổi biểu thức này vào một vị và sau đó thực hiện nó. ..
var predicate =
(Func<Product, bool>)Expression.Lambda(andExpression, product).Compile();
var query = Enumerable.Where(YourDataContext.Products, predicate);
foreach(Product currentProduct in query)
meh(currentProduct);
Có lẽ sẽ không biên dịch vì tôi đã gõ nó trực tiếp vào trình duyệt, nhưng tôi tin nó nói chung là đúng.
cập nhật Một :-)
List<Product> products = new List<Product>();
products.Add(new Product { CategoryName = "Tops", Color = "Red" });
products.Add(new Product { CategoryName = "Tops", Color = "Gree" });
products.Add(new Product { CategoryName = "Trousers", Color = "Red" });
var query = (IEnumerable<Product>)products;
query = query.Where(p => p.CategoryName == "Tops");
query = query.Where(p => p.Color == "Red");
foreach (Product p in query)
Console.WriteLine(p.CategoryName + "/" + p.Color);
Console.ReadLine();
Trong trường hợp này, bạn sẽ được đánh giá trong bộ nhớ vì nguồn là một danh sách, nhưng nếu nguồn của bạn là một bối cảnh dữ liệu mà hỗ trợ Linq2SQL ví dụ tôi nghĩ điều này sẽ đánh giá bằng cách sử dụng SQL.
Bạn vẫn có thể sử dụng mẫu Đặc điểm kỹ thuật để làm cho các khái niệm của bạn rõ ràng.
public class Specification<T>
{
IEnumerable<T> AppendToQuery(IEnumerable<T> query);
}
Sự khác biệt chính giữa hai cách tiếp cận là sau này xây dựng một truy vấn được biết dựa trên đặc tính rõ ràng, trong khi người đầu tiên có thể được sử dụng để xây dựng một truy vấn của bất kỳ cấu trúc (ví dụ như xây dựng một truy vấn hoàn toàn từ XML ví dụ.)
Điều này là đủ để bạn bắt đầu :-)
[Lọc Design Pattern Với Ví dụ] (http://www.singhajit.com/filter-design-pattern/) –