3

说我有这个简单的课程

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 方法以向我的类添加一些行为。这在创建新对象时工作得非常好,但是当我想从数据库加载实体时,DateUpdated 当然设置为我想避免的当前日期。

是否有任何模式可以用来避免公开 DateUpdated 设置器,因为这似乎破坏了我的良好封装并弄乱了类的干净接口?当然,这个类只是一个更一般的问题的例子。

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

4

5 回答 5

4

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

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

public MyEntity(DateTime dateUpdated, string author, string comment)
{
  DateUpdated = dateUpdated;
  Author = author;
  Comment = comment;
}
于 2012-08-03T13:10:33.837 回答
3

查看 Memento 模式,为您的对象补充水分。仅将构造函数用于创建新实例。

于 2012-08-20T20:12:31.597 回答
1

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

于 2012-08-09T00:22:32.490 回答
1

您可以像这样重载 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;
    }
}
于 2012-08-03T13:24:16.113 回答
0

如果负责创建这些对象的存储库位于同一个程序集中,则应检查内部访问修饰符。如果这符合您项目的需求,您可以通过以下两种方式之一来实现它...

  1. 将您的设置器从 更改privateinternal。然后,创建者只需在实例化后设置属性的值。
  2. 添加一个internal构造函数,该构造函数接受所有属性的值并设置它们。

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

于 2012-08-03T17:11:30.947 回答