2

在我的应用程序的域核心中,我有一个Order对象。它具有私有设置器,因为不应随意修改这些属性,而只能在对对象执行公共功能之一的上下文中进行修改。

public class Order
{
    public int Id { get; private set; }
    public int MarketplaceId { get; private set; }
    public int CustomerId { get; set; }
    public OrderStatus Status { get; private set; }

    public bool Validate() { //stuff }
    public void Fulfill()
    {
        //messes with order status, etc.
    }

}

我有一个OrderRepository用于数据访问的,它位于我的架构的外部边缘,它有一个GetOrderById(int orderId)功能。此函数从数据库中提取以填充Order对象。我需要能够填充我的Order对象,但我宁愿不将属性公开,因为使用该Order对象的任何其他应用程序或服务都不应该设置这些属性。我如何构建它以Order从存储库中填充对象,但仍保留我对Order对象的封装?

似乎通过一个或多个构造函数(重载)执行此操作会很麻烦,但我不确定还能做什么。

4

4 回答 4

0

该订单是一个对象,但我很确定不是域对象。Validate() 和 Fulfill() 在那里没有位置,但这是另一回事。

是否使用 ORM 并不重要,重要的是对象状态的存储方式。在您的情况下,最直接的方法是使用 AutoMapper 从 EF 实体映射到 Order,或者(我赞成这种方法)拥有一个 OrderStateSave DTO,它将作为构造函数参数传递。

就我个人而言,我更喜欢直接序列化对象,因此恢复是一个微不足道的反序列化。为简单起见,这意味着我在 PK 列旁边有一列序列化。保存时这是一个额外的步骤,但它很容易。

于 2013-05-17T10:47:13.773 回答
0

You should have a look at this interesting article, it summarizes what you're trying to do: Strengthening your domain by disabling setters.

于 2013-05-17T08:17:05.997 回答
0

如何构建它以从存储库中填充 Order 对象,但仍保留我对 Order 对象的封装?

您需要使用Object-relational mapper好的 ORM将允许您填充私有字段,以便您可以在您的域对象中进行适当的封装。

似乎通过一个或多个构造函数(重载)执行此操作会很麻烦,但我不确定还能做什么。

NHibernate 对域对象的唯一要求是它有一个空的私有构造函数。还要注意流行的“Fluent/Code”映射,这使得字段保密变得困难。相反,您可以只使用经典的 HBM 映射文件,并通过编写集成测试来捕获所有潜在的映射错误。

于 2013-05-16T23:02:11.480 回答
0

通过使用反射:

var order = new Order();
order
   .GetType()
   .GetProperty("MarketplaceId", BindingFlags.Instance|BindingFlags.NonPublic)
   .SetValue(order, 20);

还有几个示例使用委托进行分配(以使其更快)。这是我几年前做的一个例子:https ://webserver.codeplex.com/SourceControl/latest#693649

于 2013-05-17T06:10:11.880 回答