3

我的问题很简单:如何将我班级的私有数据保存到存储库中?

不管我们采用何种架构风格,每个人都同意业务对象不应该知道“如何”保存自己——也就是说,它们不应该实现数据库或其他持久性细节。但是,在我看来,业务对象是唯一知道他们需要保存“什么”的对象。Repository 知道如何从数据库中获取,但如果它要知道如何将业务对象翻译成数据库术语,那么它必须知道要翻译什么。

考虑到我可能使用数据库,但我没有用休眠注释标记我的类,因为我可能经常保存到平面文本文件中。

假设我在这里的课程实际上是以特定的业务实体命名的,那么做类似的事情会有什么问题

interface Exporter
{
    public void Export(String id, String value1, String value2);
}

interface Repository
{
    public Entity FindById(String id);
}

class Entity
{
    private String id;
    private String value1;
    private String value2;
    private String derivedvalue;

    public Entity() {}

    public Entity(String id, String value1, String value2)
    {
        this.id = id;
        this.value1 = value1;
        this.value2 = value2;
        this.derivedvalue = /* derived from id, value1, and value2 */;
    }

    public void DoBusiness()
    {
        // ...
    }

    public void Export(Exporter exporter)
    {
        Exporter.Export(this.id, this.value1, this.value2);
    }
}

并像使用它一样

FlatFileRepositoryAndExporter flatfile = new FlatFileRepositoryAndExporter(...);
Entity entity = flatfile.FindById(...);

// Do business logic
entity.DoBusiness();

entity.Export(flatfile);

我知道有一些框架可以帮助我,但归根结底,它们都依赖于某种反射。我想知道,在没有反射的情况下,我如何静态组合我的对象以在保持封装的同时公开它们的数据。我能想出的唯一答案是这种访问者模式。

4

2 回答 2

2

我倾向于同意@MikeSW 的观点,即借助较小的范围调整(或像 ORM 那样的反射),使外部持久性工具能够收集域对象状态通常比让域对象本身完全控制持久化的内容更简单。

还有第三种方法是让实体发出事件来描述发生的事情,而不是暴露其状态——这就是事件溯源。然后,任何想要的人都可以倾听这些并以他们想要获得的任何形式坚持改变。

于 2015-06-22T08:52:49.803 回答
1

不要让你的生活过于复杂。你想要做的基本上是一个纪念品,它可以工作,但它的维护成本很高(因为非常无聊)。我通常 json 序列化事物,无论我实际将它们存储在哪里,并且我已经将 json.net 配置为序列化受保护的属性。所以基本上,我有受保护的属性或只是受保护的设置器,它工作得很好。

虽然不是一个纯粹的解决方案,但妥协非常低,对象的内部不会暴露给它的用户。你可以拥有类似的东西

 private List<string>_data=new List<string>();
public IEnumerable<string> Data 
{
   get { return _data;}
   protected set {  _data=value.ToList(); }

}

这种方法很简单,非常可维护并且与持久性工具无关。

顺便说一句,出口商,考虑到它的目的,应该只与公共成员打交道,而对象不应该知道它。

于 2015-06-20T15:02:43.360 回答