当您可以使用Dynamic LINQ时,规范模式是否已过时?

时间:2009-09-21 11:28:08

标签: linq dynamic-linq specification-pattern

Wikipedia表明规范模式是通过使用布尔逻辑将业务逻辑链接在一起来重新组合业务逻辑的地方。关于从列表或集合中选择过滤对象,在我看来,Dynamic LINQ允许我完成同样的事情。我错过了什么吗?是否还应考虑规范模式的其他好处?


编辑:

我发现了一些讨论组合LINQ和规范模式的帖子:

Linq Specifications Project

Implementing the Specification Pattern via Linq by Nicloas Blumhardt (Autofac dude)

有没有人走过这条路并且维修变得复杂了?

4 个答案:

答案 0 :(得分:5)

我是C#开发人员,喜欢使用规范模式,因为它离我的业务领域更近。此外,您对此模式没有任何意外,如果存在规范类,它应该可以工作。使用Linq,您的底层提供程序可能还没有实现某些功能,直到运行时才会知道它。

但最终,规格优于linq的最大优势是更接近业务,它是一个迷你DSL。 LINQ for me是用于收集查询的DSL,而不是用于业务领域。

答案 1 :(得分:2)

动态LINQ使用字符串表达式来允许动态查询构造。所以我们确实失去了那里的类型安全。而使用包装器模式,如它的装饰器模式密切相关的化身,规范模式,允许我们在代码中维护类型安全。我探索使用Decorator Pattern作为查询包装器,以便重用和动态构建查询。您可以在以下位置找到有关代码项目的文章: Linq Query Wrappers

或者您可以查看我的blog

答案 2 :(得分:1)

我真的不知道LINQ,但在我看来,声明性查询系统通常与规范模式有关。特别是,通过在面向对象的环境中将对象组合在一起来实现声明性查询系统。 IIRC类似于LINQ所做的,提供了一层语法糖。

LINQ是否完全废弃了模式,我无法分辨。也许有些案例无法在LINQ中表达?

答案 3 :(得分:1)

<强> LINQ:

var oldMans = Persons.Where(x => x.Sex == SexEnum.Masculine && x.Age > 60).ToList();

<强>规格:

var oldMans = Persons.Where(x => IsOldManSpecification(x)).ToList();
  • 业务逻辑封装在规范中(名称显示它是什么)。
  • DRY:您不会在代码上重复该linq,只需使用规范

当我认为 规则非常重要,在代码中明确表示并且它并不属于实体 时,我喜欢使用规范。

示例:

public class Customer
{
    //...

    public bool IsAbleToReceiveCredit(decimal creditValue)
    {
        var secureAge = this.Age > 18 && this.Age < 60;
        var personalAssetsGreaterThanCreditValue = this.PersonalAssets.Sum(x => x.Value) > creditValue;

        return secureAge && personalAssetsGreaterThanCreditValue;
    }
}

是否来自Customer 责任来决定他是否能够获得一些信用?银行会询问客户是否可以获得贷款?

可能不是。

因此,通过规范,您可以从Customer中删除该逻辑(它永远不属于它)。您可以创建类似IsAbleToReceiveCreditSpecification的内容并将所有逻辑放在那里。我们可以进一步整合规范,例如:您可以创建SecureAgeSpecificationAssetsGreaterThanSpecification并使用它们来撰写IsAbleToReceiveCreditSpecification

所以我不认为LINQ取代了规范。实际上它改善了模式。有一些规范的实现在内部使用LINQ IQueriable<T>,你可以在Repository / DataAcess级别使用ORM查询中的规范。