背景
Udi Dahan 建议将获取策略作为用于数据访问的有用模式。我同意。
这个概念是使角色明确。例如,我有一个聚合根 - 客户。我希望客户在我的应用程序的几个部分中 - 可供选择的客户列表,客户详细信息的视图,并且我想要一个按钮来停用客户。
似乎 Udi 会为这些角色中的每一个建议一个界面。所以我有ICustomerInList
非常基本的细节,ICustomerDetail
其中包括最近购买的 10 种产品,并且IDeactivateCustomer
有一种方法可以停用客户。每个接口都暴露了我的客户聚合根,以便在每种情况下完成工作。我的客户聚合根实现了所有这些接口。
现在我想为每个角色实现一个获取策略。每种策略都可以将不同数量的数据加载到我的聚合根中,因为它将位于只公开所需信息位的接口后面。
实现这部分的一般方法是询问服务定位器或其他样式的依赖注入。例如,此代码将获取您想要的接口ICustomerInList
,并找到一个获取策略来加载它(IStrategyForFetching<ICustomerInList>
)。这个策略是由一个类实现的,该类知道只加载具有 ICustomerInList 接口所需的信息位的客户。
到目前为止,一切都很好。
问题
您传递给服务定位器或IStrategyForFetching<ICustomerInList>
. 我看到的所有示例都仅通过已知 ID 选择一个对象。这种情况很简单,调用代码通过这个id,会得到具体的接口。
如果我想搜索怎么办?或者我想要客户列表的第 2 页?现在我想传递更多获取策略所需的术语。
可能的解决方案
我见过的一些示例使用谓词 - 如果特定聚合根应该是结果集的一部分,则返回 true 或 false 的表达式。这在条件下工作得很好,但是让前 n 个客户回来而不是更多呢?或者获取搜索结果的第 2 页?或者结果如何排序?
我的第一反应是开始向我的IStrategyForFetching<ICustomerInList>
It now添加泛型参数IStrategyForFetching<TAggregateRoot, TStrategyForSelecting, TStrategyForOrdering>
。这很快变得复杂而丑陋。不同的存储库使情况更加复杂。一些存储库仅在使用特定策略进行选择时提供数据,有些仅提供某些类型的排序。我希望能够灵活地实现可以采用排序功能的通用存储库以及仅返回以特定方式排序的聚合根的专用存储库。
听起来我应该应用开始时使用的相同模式 - 如何明确角色?我是否应该使用有效负载 Y(搜索/排序参数)实施获取 X(聚合根)的策略?
编辑 (2012-03-05)
如果我不是每次都返回聚合根,这一切仍然有效。如果每个接口由不同的 DTO 实现,我仍然可以使用 IStrategyForFetching。这就是这种模式强大的原因 - 获取和返回的内容不必以任何方式映射到聚合根。
我最终使用了IStrategyForFetching<TEntity, TSpecification>
. TEntity 是我想要得到的东西,TSpecification 是我想要得到它的方式。