DDD封装和存储库模式

说我有这个简单的课程

public class MyEntity
{
    public DateTime DateUpdated { get; private set; }
    public string Author { get; private set; }
    public string Comment { get; private set; }

    public void AddComment(string comment, string author)
    {
        Author = author;
        Comment = comment;
        DateUpdated = DateTime.Now;
    }
}

我已将setter私有化以封装该类,并添加了AddComment方法以向我的类添加一些行为 . 这在创建新对象时非常正常,但是当我想从db加载Entity时,DateUpdated当然设置为我想要避免的当前日期 .

是否有任何模式可以避免使DateUpdated setter公开,因为这似乎打破了我很好的封装并弄乱了类的干净界面?该课程当然只是一个更通用的问题的例子 .

在没有制作更多公共构造函数的情况下,我现在最接近的是创建一个私有构造函数,我通过公共静态方法访问它 .

回答(5)

3 years ago

使用带有与对象字段匹配的参数的构造函数 .

这将允许您在启动时填充对象并使它们保持不变 .

public MyEntity(DateTime dateUpdated, string author, string comment)
{
  DateUpdated = dateUpdated;
  Author = author;
  Comment = comment;
}

3 years ago

查看Memento图案,重新保湿您的物体 . 仅将构造函数用于创建新实例 .

3 years ago

您可以像这样重载AddComment方法:

public class MyEntity
{
    public DateTime DateUpdated { get; private set; }
    public string Author { get; private set; }
    public string Comment { get; private set; }

    public void AddComment(string comment, string author)
    {
        Author = author;
        Comment = comment;
        DateUpdated = DateTime.Now;
    }

    public void AddComment(string comment, string author, DateTime dateUpdated)
    {
        Author = author;
        Comment = comment;
        DateUpdated = dateUpdated;
    }
}

3 years ago

如果使用NHM等ORM来实现存储库,那么即使属性是私有集,它也会根据数据库中的数据为属性赋值 . 换句话说,它绕过 AddComment 方法并直接注入数据 . 这是有道理的,因为在重构实体时,行为不会重复,只需要复制数据 . NHibernate确实要求实体包含受保护的无参数构造函数 . 如果使用自己的ORM实现,那么您可以使用Oded建议的构造函数模式,因为在这种情况下,您的实体可以真正保持持久性无知 .

3 years ago

如果负责创建这些对象的存储库位于同一个程序集中,则应该查看internal access modifier . 如果这符合您项目的需求,您可以通过以下两种方式之一实现它......

  • 将您的二传手从 private 更改为 internal . 然后,创建者只需在实例化后设置属性的值 .

  • 添加 internal 构造函数,该构造函数接受所有属性的值并进行设置 .

无论哪种方式,您仍然可以通过示例中演示的公共方法进行更改 .