将DTO映射到域对象的最佳实践?

我已经看到很多与将DTO映射到域对象有关的问题,但我不觉得他们回答了我的问题。 我以前用过很多方法,有我自己的看法,但是我正在寻找更具体的东西。

情况:

我们有许多域对象。 我们使用CSLA模型,所以我们的域对象可能非常复杂,并且包含他们自己的数据访问。 你不想在电线上传递这些信息。 我们将要编写一些新的服务,以多种格式(.Net,JSON等)返回数据。 为了这个(和其他原因),我们还创build了一个精简的数据传输对象来传递线路。

我的问题是DTO和Domain对象应该如何连接?

我的第一反应是使用Fowler,DTO模式types的解决scheme 。 我已经看过很多次了,这感觉对我来说很合适。 域对象不包含对DTO的引用。 调用外部实体(“映射器”或“汇编器”)以从域对象创buildDTO。 通常在域对象上有一个ORM。 这样做的缺点是,“映射器”往往对于任何实际情况都非常复杂,并且可能非常脆弱。

另一个想法是域对象“包含”DTO,因为它只是一个精益数据对象。 域对象属性将在内部引用DTO属性,如果需要可以返回DTO。 我可以看到没有问题,但感觉不对。 我看过一些使用NHibernate的人似乎使用这种方法的文章。

还有其他的方法吗? 以上方法之一值得使用吗? 如果这样或者没有,为什么?

提前感谢您的任何见解。

当你只支持一个映射时,映射器位于你的域和你的DTO之间的好处就不那么明显了,但随着映射数量的增加,把域与代码域隔离开来有助于保持域更简单和更精简。 你不会因为额外的重量而混淆你的域名。

就我个人而言,我试图将我的域名实体映射出来,并把责任放在我所说的“经理/服务层”。 这是一个位于应用程序和存储库之间的层,并提供业务逻辑,如工作stream协调(如果您修改A,则可能还需要修改B,以便服务A将与服务B协同工作)。

如果我有很多可能的结束格式,我可能会考虑创build一个可以使用访问者模式的可插入格式化程序,例如来转换我的实体,但是我还没有发现任何这种复杂的需求。

你可以使用一个自动映射器,比如Jimmy Bogard写的一个自动映射器,这个对象之间没有任何联系,依赖于遵守的命名约定。

我们使用T4模板来创build映射类。

Pro的 – 编译时可用的人类可读代码,比运行时映射器更快。 对代码100%的控制(可以使用部分方法/模板模式来在特定的基础上扩展function)

Con的 – 不包括某些属性,领域对象的集合等,学习T4语法。

另一个可能的解决scheme: http : //glue.codeplex.com 。

特征:

  • 双向映射
  • 自动映射
  • 不同types之间的映射
  • 嵌套映射和展平
  • 列表和数组
  • 关系validation
  • testing映射
  • 属性,字段和方法

你如何看待在DTO类中实现一个构造函数作为一个域对象的参数?

说…这样的事情

class DTO { // attributes public DTO (DomainObject domainObject) { this.prop = domainObject.getProp(); } // methods } 

您也可以尝试Otis,一个Object-to-object映射器。 概念与NHibernate映射(属性或XML)类似。

http://code.google.com/p/otis-lib/wiki/GettingStarted

我可以推荐一个我创build的工具,它是在CodePlex: EntitiesToDTOs托pipe的开源代码。

从DTO到实体的映射(反之亦然)是通过扩展方法实现的,它们组成了每一端的汇编器端。

你以代码结束:

 Foo entity = new Foo(); FooDTO dto = entity.ToDTO(); entity = dto.ToEntity(); List<Foo> entityList = new List<Foo>(); List<FooDTO> dtoList = entityList.ToDTOs(); entityList = dtoList.ToEntities(); 

为什么我们不能这样做?

 class UserDTO { } class AdminDTO { } class DomainObject { // attributes public DomainObject(DTO dto) { this.dto = dto; } // methods public function isActive() { return (this.dto.getStatus() == 'ACTIVE') } public function isModeratorAdmin() { return (this.dto.getAdminRole() == 'moderator') } } userdto = new UserDTO(); userdto.setStatus('ACTIVE'); obj = new DomainObject(userdto) if(obj.isActive()) { //print active } admindto = new AdminDTO(); admindto.setAdminRole('moderator'); obj = new DomainObject(admindto) if(obj.isModeratorAdmin()) { //print some thing } 

@FrederikPrijck (或)某人:请build议。 在上面的例子中,DomainObject依赖于DTO。 通过这种方式,我可以避免代码做映射dto < – > domainobject。

或DomainObject类可以扩展DTO类?