我有一个数据库表,其中包含产品列表(服装).产品属于类别,来自不同的商店.
样品类别:上衣,下装,鞋子
样品商店:gap.com,macys.com,target.com
我的客户可以通过以下方式请求过滤产品:
现在我在"Products"类中有一个方法,它根据用户请求的过滤器类型返回产品.我使用FilterBy枚举来确定需要返回哪些产品.
例如,如果用户想要查看"tops"类别中的所有产品,我会调用此函数:
Products.GetProducts(FilterBy.Category, "tops", "");
Run Code Online (Sandbox Code Playgroud)
我有最后一个参数为空,因为它是包含要过滤的"商店"的字符串,但在这种情况下没有商店.但是,如果用户想要按类别和商店进行过滤,我会以这种方式调用方法:
Product.GetProducts(FilterBy.CategoryAndStore, "tops", "macys.com");
Run Code Online (Sandbox Code Playgroud)
我的问题是,有什么更好的方法呢?我刚学会了战略设计模式.我可以使用它以更好(更容易扩展和更容易维护)的方式做到这一点吗?
我问这个问题的原因是因为我认为这一定是人们反复解决的一个非常普遍的问题(以各种方式过滤产品)
Pet*_*ris 13
根据Eric Evan的"域驱动设计",您需要规范模式.像这样的东西
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 } + "'";
}
}
Run Code Online (Sandbox Code Playgroud)
现在可以使用规范调用您的存储库
var specifications = new List<ISpecification<Product>>();
specifications.Add(
new ProductCategoryNameSpecification("Tops"));
specifications.Add(
new ProductColorSpecification("Blue"));
var products = ProductRepository.GetBySpecifications(specifications);
Run Code Online (Sandbox Code Playgroud)
您还可以创建一个通用的CompositeSpecification类,该类包含子规范和关于应用于哪个逻辑运算符的指示符和/或
我更倾向于结合LINQ表达式.
更新 - 运行时LINQ的示例
var product = Expression.Parameter(typeof(Product), "product");
var categoryNameExpression = Expression.Equal(
Expression.Property(product, "CategoryName"),
Expression.Constant("Tops"));
Run Code Online (Sandbox Code Playgroud)
您可以像这样添加"和"
var colorExpression = Expression.Equal(
Expression.Property(product, "Color"),
Expression.Constant("Red"));
var andExpression = Expression.And(categoryNameExpression, colorExpression);
Run Code Online (Sandbox Code Playgroud)
最后,您可以将此表达式转换为谓词,然后执行它...
var predicate =
(Func<Product, bool>)Expression.Lambda(andExpression, product).Compile();
var query = Enumerable.Where(YourDataContext.Products, predicate);
foreach(Product currentProduct in query)
meh(currentProduct);
Run Code Online (Sandbox Code Playgroud)
可能不会编译因为我直接在浏览器中键入它,但我相信它通常是正确的.
另一个更新 :-)
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();
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您将在内存中进行评估,因为源是List,但如果您的源是支持Linq2SQL的数据上下文,例如我认为这将使用SQL进行评估.
您仍然可以使用规范模式以使您的概念明确.
public class Specification<T>
{
IEnumerable<T> AppendToQuery(IEnumerable<T> query);
}
Run Code Online (Sandbox Code Playgroud)
两种方法的主要区别在于后者基于显式属性构建已知查询,而第一种方法可用于构建任何结构的查询(例如,完全从XML构建查询).
这应该足以让你入门:-)
| 归档时间: |
|
| 查看次数: |
5497 次 |
| 最近记录: |