一、AutoMapper
AutoMapper是什么?AutoMapper是一个.NET的对象映射工具。
映射什么?映射的场景有:领域对象与DTO之间的转换、数据库查询结果映射至实体对象。
具体关于AutoMapper 的概念,这里就不再多说,场景详细请看。
最近在项目的时候就遇到其中的一个场景:对象实体想DTO的转换。 底层使用的思想是ORM.在ORM中,与数据库交互用的Model模型是具有很多属性变量方法这些,而当我们与其它
系统(或系统中的其它结构)进行数据交互时,出于耦合性考虑或者安全性考虑或者性能考虑(总之就是各种考虑),
我们不希望直接将这个Model模型暴露给外界,这时我们会创建一个DTO模型(贫血模型)来保存数据并传递。
(DTO,Data Transfer Object)就是说只包含属性,只能保存必须的数据,没有其它任何的多余的方法数据什么的,
专门用于数据传递用的类型对象。
二、转换方式
这样的一个场景,我们就需要一个方法来帮助我们来进行DTO和Entity之间转换。
转换又分几种方式,一种就是比较简单的相同类型之间的转换。例如:Controls 转换成ControlsViewModel
<span style="font-family:KaiTi_GB2312;font-size:18px;">public partial class Controls { public string ControlId { get; set; } public string ControlType { get; set; } public string ControlDesc { get; set; } }</span>
<span style="font-family:KaiTi_GB2312;font-size:18px;"> [DataContract] public class ControlsViewModel { [DataMember] public string ControlId { get; set; } /// <summary> /// 控件类型 /// </summary> [DataMember] public string ControlType { get; set; } /// <summary> /// 控件描述 /// </summary> [DataMember] public string ControlDesc { get; set; } }</span>
可以看到两个实体中包含的属性的类型都是相同类型的,这样的转换我们只需要属性一一匹配就行了,方法参考
还有另一种情形——实体中包含的属性类型不一样,即A 实体中包含的属性A1是 C类型的,但是B实体中与A1对应的B1是D类型的,这个时候,如何实现A1到B1的转换呢?
如果你的C 和D 类型是 System的包含的已有类型,如:int ,string ,datatime ……这些,可以参考这里。
今天的主题现在开始正式进入,这篇博客说的是自定义类型之间的转换。即:C ,D 不是System已包含的实体,是自己定义的。
情景如下:实体模型如下,其中包含一个Controls 的自定义类型。
<span style="font-family:KaiTi_GB2312;font-size:18px;">public partial class QueryProperties { public string QueryId { get; set; } public string PropertyName { get; set; } public string PropertyDesc { get; set; } public string ControlHtmlName { get; set; } public string ControlHtmlId { get; set; } public string IsShow { get; set; } public string EntityName { get; set; } public string EntityDesc { get; set; } public string IsCondition { get; set; } public virtual Controls Controls { get; set; } }</span>
目标模型如下:跟实体模型QueryProperties不同的是,其中包含一个ControlViewModel的自定义类型来对应Controls实体。
<span style="font-family:KaiTi_GB2312;font-size:18px;">[DataContract] public class QueryPropertiesViewModel { [DataMember] public string QueryId { get; set; } [DataMember] public string PropertyName { get; set; } [DataMember] public string PropertyDesc { get; set; } [DataMember] public string ControlHtmlName { get; set; } [DataMember] public string ControlHtmlId { get; set; } [DataMember] public string IsShow { get; set; } [DataMember] public string EntityName { get; set; } [DataMember] public string EntityDesc { get; set; } [DataMember] public string IsCondition { get; set; } [DataMember] public virtual ControlsViewModel Controls { get; set; } }</span>
如果单纯的使用:AutoMapper 中:Mapper.Map<Tsource,TDestination>(tSource) ,它会转换失败,告诉你类型不匹配。要想成功转换,我们第一步需要让Mapper认识Controls 和ControlViewModel 是一对的,可以相互转换。
添加如下声明代码:
<span style="font-family:KaiTi_GB2312;font-size:18px;"> Mapper.CreateMap<ControlsViewModel, Controls>();</span>然后声明主体对象:
<span style="font-family:KaiTi_GB2312;font-size:18px;"> var expression = Mapper.CreateMap<QueryPropertiesViewModel,QueryProperties>();</span>指明匹配属性:
<span style="font-family:KaiTi_GB2312;font-size:18px;"> expression.ForMember(s => s.Controls, (map) => map.MapFrom(m => m.Controls));</span>开始转换:
<span style="font-family:KaiTi_GB2312;font-size:18px;"> QueryProperties enQueryProperties = Mapper.Map<QueryPropertiesViewModel, QueryProperties>(viewQueryProperties);</span>
代码中,单个实体不和其他实体打交道的类少只有少,这就是我们所谓的实体级联转换。希望可以帮到你们。