在图层之间复制模型

Pag*_*age 8 architecture asp.net-mvc automapper asp.net-mvc-2

遍历图层时,执行right-> left赋值作为填充模型的方法非常繁琐.例如:

employeeViewModel.FirstName = employeeModel.FirstName;
employeeViewModel.LastName = employeeModel.LastName;
...
Run Code Online (Sandbox Code Playgroud)

因此,我们可以构建一个使用反射来复制模型的ModelCopier:

var employeeViewModel = ModelCopier.Copy<EmployeeViewModel>(employeeModel);
Run Code Online (Sandbox Code Playgroud)

这种技术大大简化了任务.但是,有一些事情令人非常不安:

  • 我们实际上已经无法跟踪源和目标对象上的属性的使用情况.例如,查找FirstName属性的使用(在Resharper中)不会显示ModelCopier案例.
  • 如果我们更改源类或目标类上的属性的名称,我们可能会无意中导致运行时异常,因为我们可能没有意识到我们需要更新源类和目标类.

在光谱的一端,我们可以使用非常容易的反射,但是以可维护性为代价.频谱的另一端是非常繁琐但非常可维护的.

反思(轻松和危险)<----->直接分配(繁琐且可维护)

我很好奇是否有人发现了一种折衷方案,它提供了易于使用反射进行复制并具有直接赋值的可维护性.

我们接受的一个解决方案是构建一个插件,该插件将生成扩展方法,以处理每种情况的属性分配.换句话说,构建一个可以处理繁琐部分的工具.

编辑:

请理解,此问题与使用哪种映射工具无关.我试图理解我们如何享受基于反射的映射的好处,同时还享受直接赋值(或属性映射契约)提供的可维护性的好处.

djd*_*d87 10

说真的,使用AutoMapper.它允许您设置从一种类型到另一种类型的转换.对属性名称的任何更改都将破坏自动化程序的配置,反射不会:

Mapper.CreateMap<SiteDto, SiteModel>();
Mapper.CreateMap<SiteModel, SiteDto>();
Run Code Online (Sandbox Code Playgroud)

然后要映射到和来,您只需执行以下操作:

SiteDto dto = Mapper.Map<SiteModel, SiteDto>(targetModel);
SiteModel model = Mapper.Map<SiteDto, SiteModel>(targetDto);
Run Code Online (Sandbox Code Playgroud)

  • 自动映射器是确定的方法.挺好的! (2认同)
  • @jfar - 在较大的项目中,各种开发人员可以以微妙的方式更改属性名称(例如,电话,电话号码).这在开发过程中很容易被遗漏,并导致生产错误.这就是@Page Brooks所指的. (2认同)

the*_*cuz 3

编译器可能不会对整个代码进行必要的测试......这就是单元测试的用武之地。如果您已经为不同层中的类之间的转换定义了一个测试(是的,您需要执行的所有可能的转换,否则您如何确保您的反射方法在生产中适用于每种情况?),只需运行测试将告诉更改属性名称的开发人员,该解决方案不再通过所有测试。每次您想要签入源代码时,您都应该运行每个测试(单元测试,而不是集成测试)......这不应该是几个月的编码:))

所以我真的投票支持使用反射方法,辛辣的单元测试方法。

  • 最后,如果要对对象进行单元测试,为什么要使用反射呢?通过手动映射对象可以完成同样的事情。定义一个映射类。用它来在类型A和类型B之间进行映射。然后你就得到了编译器的保护,并且只有一处可以更改代码。 (3认同)