Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 恢复域对象的最佳方法_Oop_Domain Driven Design_Factory Pattern - Fatal编程技术网

Oop 恢复域对象的最佳方法

Oop 恢复域对象的最佳方法,oop,domain-driven-design,factory-pattern,Oop,Domain Driven Design,Factory Pattern,这是一个如此简单和常见的场景,我想知道我是如何管理到现在,为什么我现在有问题 我有这个对象(基础结构组件的一部分) 这将在另一个程序集中创建,如下所示 var qi = new QueueItem(1,"myname",typeof(MyCommand),null); 这里没有什么不寻常的。但是,此对象将被发送到存储库,并保存到存储库中。队列对象将向存储库请求项目。存储库应重新创建QueueItem对象 但是,正如您所看到的,QueueItem属性是不变的,在创建项时,AddedOn属性只应

这是一个如此简单和常见的场景,我想知道我是如何管理到现在,为什么我现在有问题

我有这个对象(基础结构组件的一部分)

这将在另一个程序集中创建,如下所示

 var qi = new QueueItem(1,"myname",typeof(MyCommand),null);
这里没有什么不寻常的。但是,此对象将被发送到存储库,并保存到存储库中。队列对象将向存储库请求项目。存储库应重新创建QueueItem对象

但是,正如您所看到的,QueueItem属性是不变的,在创建项时,AddedOn属性只应设置一次。Id属性将由队列对象设置(这并不重要)

问题是我应该如何在存储库中重新创建QueueItem?我可以有另一个构造函数,它需要所有属性的每个值,但我不希望该构造函数可用于最初创建队列项的程序集。存储库是另一个程序集的一部分,因此内部无法工作

我想提供一种工厂方法 类队列项 { /*…其余定义..*/

     public static QueueItem Restore(/* list of params*/){}
   }
这至少澄清了我的意图,但我不知道为什么我不喜欢这种方法。我也可以只通过队列强制创建项目,但这意味着将队列作为依赖项传递给repo,这同样不是我想要的。为此使用特定的工厂对象似乎也有点过分了

基本上,我的问题是:在存储库中重新创建对象的最佳方式是什么,而不向另一个消费者对象公开特定的创建功能

更新

需要注意的是,我所说的存储库是指模式本身作为一种抽象,而不是ORM上的包装器。它与域对象的持久化方式或位置无关。它与存储库如何重新创建有关。另一个重要的是,我的域模型与持久化模型不同trong>。我确实使用RDBMS,但我认为这只是一个实现细节,不应该有任何重要性,因为我正在寻找一种不依赖于特定存储访问的方法

虽然这是一个特定的场景,但它基本上可以应用于将由回购恢复的每个对象

更新2

好的,我不知道我怎么能忘记AutoMapper。我有一个错误的印象,它不能映射私有字段/设置器,但它可以,我认为这是最好的解决方案

事实上,我可以说最佳解决方案(IMO)的顺序如下:

  • 直接反序列化(如果可用)
  • 自动地图
  • 域对象本身上的工厂方法
  • 前两种方法不需要对象执行任何特定操作,而第三种方法需要对象为这种情况提供功能(一种输入有效状态数据的方法)。它有明确的意图,但基本上是一种映射程序

    答案已更新


    回答我自己,在这种情况下,最佳的方法是使用工厂方法。最初我选择了Automapper,但我发现自己更经常使用工厂方法。Automapper有时可能有用,但在相当多的情况下它是不够的。

    ORM框架将为您解决这一问题。您只需告诉它重新水化o对象和域类的常规实例将提供给您(有时您只需将属性声明为虚拟或受保护,例如在NHibernate中)。原因是在后台,它们通常对派生自基类的代理对象进行操作,从而使您能够保持这些基类的完整性

    但是,如果您想实现自己的持久化层,那就完全是另外一回事了。在不打破对象中最初定义的范围约束的情况下,从数据库中重新水化对象可能会涉及反射。您还必须考虑许多次要问题:如果您的对象引用了另一个对象,则必须将之前的那个水化


    您可以看看该教程:尽管我不建议在大多数情况下重新发明轮子。

    您谈到了对象本身的工厂方法。但DDD声明实体应由工厂创建。因此,您应该拥有一个QueueItemFactory,可以创建新的QueueItems并还原现有的QueueItems

    好吧,我不知道我怎么能忘记AutoMapper


    我希望我能忘记AutoMapper。仅仅看到这个可怕的API就让我不寒而栗。

    这个问题不依赖于数据库。当我说存储库时,我的意思是它完全是一个抽象。即使使用ORM,我仍然必须将ORM实体映射到域实体。我已经用这个澄清更新了我最初的问题n我猜您“只有”有以下选项:内部关键字+[InternalsVisibleTo(YourReposAssembly)]或反射或还原()方法或子类QueueItem在YourReposAssembly中…谢谢你的建议,但我认为我找到了最好的方法。我更新了问题。在这种情况下,工厂是创建实体的好选择。但这里我想还原,这是存储库的责任。我认为工厂不应该还原实体。有几个l执行恢复的方法,目前我更喜欢实体本身的静态工厂方法。实际上,存储库将工作委托给工厂(如果要恢复对象,还需要一个实例)。如果您要执行CQR,则存储库可能会将工作委派给某个对象上重播域事件的对象。存储库只是一个集合,用于保存聚合根的列表。在您的情况下,存储库将承担多个不同的责任(即更改原因).话虽如此,大多数人已经使用NHibernate;这使得
         public static QueueItem Restore(/* list of params*/){}
       }