C# DDD封装和存储库模式

C# DDD封装和存储库模式,c#,domain-driven-design,C#,Domain Driven Design,假设我有一节简单的课 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) {

假设我有一节简单的课

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加载实体时,DateUpdated当然会设置为我希望避免的当前日期

有没有什么模式可以用来避免将DateUpdated setter公开,因为这似乎破坏了我良好的封装,弄乱了类的干净接口?当然,这个类只是一个更一般问题的例子


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

使用一个构造函数,该构造函数接受与对象字段匹配的参数

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

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

您可以像这样重载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;
    }
}

如果负责创建这些对象的存储库位于同一程序集中,则应签出。如果这符合您的项目需要,您可以通过以下两种方式之一实现它

  • 将设置器从
    private
    更改为
    internal
    。然后,创建者将在实例化之后设置属性的值
  • 添加一个
    内部
    构造函数,该构造函数接受所有属性的值并进行设置

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

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

    查看Memento模式以重新水合对象。仅在创建新实例时使用构造函数。

    为什么DateUpdated的setter是私有的?依我看,实体不必事事都有私人设定者。对于值类型,这当然是另一回事。这只是任何只读属性的一个例子,只能通过我的特定方法进行更改。只是好奇,你最终为此做了什么?我也遇到了同样的问题。如果我能使该构造函数仅从存储库中可用,那么它的工作点就是隐藏对该类的其他客户端的DateUpdated字段的写访问。我知道我在这里吹毛求疵,但这更多的是封装和DDD的原则,而不是一个实际的用例。@TT。-使用此选项,您只能对字段“写入”一次(尤其是将其设置为
    只读时)。这确保它只由您选择的值填充。我不太关心对象的不变性,而是关心我向这个ClassInterest的客户机公开的类接口。您知道NHibernate是否以任何方式对您的实体进行子类化以使用受保护的构造函数吗?