在图层之间复制模型

时间:2010-08-27 13:22:14

标签: asp.net-mvc asp.net-mvc-2 architecture automapper

当遍历图层时,执行右侧>左侧分配作为填充模型的方法非常繁琐。例如:

employeeViewModel.FirstName = employeeModel.FirstName;
employeeViewModel.LastName = employeeModel.LastName;
...

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

var employeeViewModel = ModelCopier.Copy<EmployeeViewModel>(employeeModel);

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

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

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

反思(轻松和危险)&lt; -----&gt;直接分配(繁琐且可维护)

我很好奇是否有人发现了一种折衷方案,可以方便地使用反射进行复制,并具有直接分配的可维护性。

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

修改

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

5 个答案:

答案 0 :(得分:10)

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

Mapper.CreateMap<SiteDto, SiteModel>();
Mapper.CreateMap<SiteModel, SiteDto>();

然后要往返地图,您只需执行以下操作:

SiteDto dto = Mapper.Map<SiteModel, SiteDto>(targetModel);
SiteModel model = Mapper.Map<SiteDto, SiteModel>(targetDto);

答案 1 :(得分:3)

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

所以我真的投票反对使用反思方法,用一勺单位测试方法辛辣。

答案 2 :(得分:1)

  

我很好奇是否有人找到了   提供便利的妥协   使用反射进行复制   直接转让的可维护性。

听起来你正试图吃蛋糕并吃掉它。

这是动态语言每天都面临的问题。没有神奇药丸。要么执行左手右手分配并获得编译器的保护,要么将您的关键任务包装在单元测试中。

我的直觉告诉我这是一个设计问题,而不是代码问题。

答案 3 :(得分:0)

一种方法是编写一个单独的实用程序,该实用程序使用反射从模型中获取属性的名称,然后编写源代码以公开属性。

答案 4 :(得分:0)

您的要求超出了运行时(实现),因为您(以及我们所有人)都需要依赖图等。这意味着带有反射的动态发现已经完成。 您似乎需要一个编译时解决方案。除了@ amaca建议的代码生成插件(你可以轻松编写),还有什么其他选择?