技术开发 频道

C#中Specification模式的实现

  这种做法是非常有实用价值的。因为有了LINQ,因此许多朋友都会选择在数据访问层暴露一个这样的方法给上层调用:

class ProductDao
{
    
public Product GetProduct(Expression<Func<Product, bool>> predicate)
    {
        ...
    }
}

  但是您有没有想过这么做的缺点是什么呢?这么做的缺点便是“过于自由”。由于GetProduct方法只将参数限制为一个Expression<Func<Product, bool>>对象,因此在调用的时候,我们可以使用任意的形式进行传递。因此,外层完全有可能传入一个目前LINQ Provider不支持的表达式树形式,也完全有可能传入一个虽然支持,但会导致查询速度慢,影响项目整体性能的表达式树。前者要在运行时才抛出异常,而后者则引发的性能问题则更难发现。因此我认为,数据访问层不应该如此自由,它要做出限制。而限制的方式,便是使用Query Object模式,让GetProduct方法接受一个受限的Query对象:

public abstract class ProductQuery
{
    
internal ProductQuery(Expression<Func<Product, bool>> query)
    {
        
this.QueryExpression = query;
    }

    
public Expression<Func<Product, bool>> QueryExpression { get; private set; }
}

class ProductDao
{
    
public Product GetProduct(ProductQuery predicate)
    {
        ...
    }
}

  而在使用时,我们只提供有限的几种条件,如:

public class ProductIdEqQuery : ProductQuery
{
    
public ProductIdEqQuery(int id)
        :
base(p => p.ProductID == id)
    { }
}

public class ProductViewRangeQuery : ProductQuery
{
    
public ProductViewRangeQuery(int min, int max)
        :
base(p => p.ViewCount > min && p.ViewCount < max)
    { }
}

  再加上配套的扩展方法用于And,Or,Not,于是一切尽在掌握。现在再去瞅瞅原Query Object模式中复杂的实现,您是否会有一种满足感?

0
相关文章