简体   繁体   English

DDD封装和存储库模式

[英]DDD encapsulation and the repository pattern

Say I have this simple class 说我有这个简单的课程

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;
    }
}

I have made the setters private to encapsulate the class and added the AddComment method to add some behaviour to my class. 我已将setter私有化以封装该类,并添加了AddComment方法以向我的类添加一些行为。 This works perfectly fine when creating a new object but when I want to load the Entity from the db the DateUpdated is of course set to the current date which I would like to avoid. 这在创建新对象时非常正常,但是当我想从db加载Entity时,DateUpdated当然设置为我想要避免的当前日期。

Is there any patterns I could use to avoid making the DateUpdated setter public as that does seem to break my nice encapsulation and messing up the clean interface of the class? 是否有任何模式可以用来避免将DateUpdated setter公开,因为这似乎打破了我很好的封装并弄乱了类的干净界面? The class is of course just an example of a more generic problem. 该课程当然只是一个更通用的问题的例子。

The closest I have got to now without making more public constructors is creating a private constructor which I access through a public static method. 在没有制作更多公共构造函数的情况下,我现在最接近的是创建一个私有构造函数,我通过公共静态方法访问它。

Use a constructor that takes parameters matching the fields of the object. 使用带有与对象字段匹配的参数的构造函数。

This will allow you to populate the objects on startup and keep them immutable. 这将允许您在启动时填充对象并使它们保持不变。

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

Look into the Memento pattern for re-hydrating your object. 查看Memento图案,重新保湿您的物体。 Use the constructor only for creating a new instance. 仅将构造函数用于创建新实例。

You can overload the AddComment method like so: 您可以像这样重载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;
    }
}

If you are using an ORM such as NHibernate to implement the repository, then it will assign values to properties based on data from the database even if the properties are private set. 如果使用NHM等ORM来实现存储库,那么即使属性是私有集,它也会根据数据库中的数据为属性赋值。 In other words, it bypasses the AddComment method and injects data directly. 换句话说,它绕过AddComment方法并直接注入数据。 This makes sense because when reconstituting an entity, behavior doesn't repeat, only the data needs to be copied. 这是有道理的,因为在重构实体时,行为不会重复,只需要复制数据。 NHibernate does require the entity to contain a protected parameter-less constructor. NHibernate确实要求实体包含受保护的无参数构造函数。 If using your own ORM implementation, then you can employ the constructor pattern as suggested by Oded because in that case your entity can truly remain persistence ignorant. 如果使用自己的ORM实现,那么您可以使用Oded建议的构造函数模式,因为在这种情况下,您的实体可以真正保持持久性无知。

If the repository responsible for creating these objects lives in the same assembly, you should check out the internal access modifier . 如果负责创建这些对象的存储库位于同一个程序集中,则应该检查内部访问修饰符 If this fits your project's needs, you can implement it in one of two ways... 如果这符合您项目的需求,您可以通过以下两种方式之一实现它......

  1. Change your setters from private to internal . 将您的二传手从private更改为internal The creator would then just set the values of the properties after instantiation. 然后,创建者只需在实例化后设置属性的值。
  2. Add an internal constructor that accepts a value for all the properties and sets them up. 添加一个internal构造函数,该构造函数接受所有属性的值并设置它们。

Either way, you can still allow change through public methods as you demonstrated in your example. 无论哪种方式,您仍然可以通过示例中演示的公共方法进行更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM