AutoMapper的介绍与使用(二)
AutoMapper的匹配
1,智能匹配
AutoMapper能够自动识别和匹配大部分对象属性:
- 如果源类和目标类的属性名称相同,直接匹配,不区分大小写
- 目标类型的CustomerName可以匹配源类型的Customer.Name
- 目标类型的Total可以匹配源类型的GetTotal()方法
2,自定义匹配
Mapper.CreateMap<CalendarEvent, CalendarEventForm>() //属性匹配,匹配源类中WorkEvent.Date到EventDate
.ForMember(dest => dest.EventDate, opt => opt.MapFrom(src => src.WorkEvent.Date))
.ForMember(dest => dest.SomeValue, opt => opt.Ignore()) //忽略目标类中的属性
.ForMember(dest => dest.TotalAmount, opt => opt.MapFrom(src => src.TotalAmount ?? 0)) //复杂的匹配
.ForMember(dest => dest.OrderDate, opt => opt.UserValue<DateTime>(DateTime.Now)); //固定值匹配
直接匹配
源类的属性名称和目标类的属性名称相同(不区分大小写),直接匹配,Mapper.CreateMap<source,dest>();无需做其他处理,此处不再细述
Flattening
将一个复杂的对象模型拉伸为,或者扁平化为一个简单的对象模型,如下面这个复杂的对象模型:
public class Order
{
private readonly IList<OrderLineItem> _orderLineItems = new List<OrderLineItem>(); public Customer Customer { get; set; } public OrderLineItem[] GetOrderLineItems()
{
return _orderLineItems.ToArray();
} public void AddOrderLineItem(Product product, int quantity)
{
_orderLineItems.Add(new OrderLineItem(product, quantity));
} public decimal GetTotal()
{
return _orderLineItems.Sum(li => li.GetTotal());
}
} public class Product
{
public decimal Price { get; set; }
public string Name { get; set; }
} public class OrderLineItem
{
public OrderLineItem(Product product, int quantity)
{
Product = product;
Quantity = quantity;
} public Product Product { get; private set; }
public int Quantity { get; private set; } public decimal GetTotal()
{
return Quantity * Product.Price;
}
} public class Customer
{
public string Name { get; set; }
}
我们要把这一复杂的对象简化为OrderDTO,只包含某一场景所需要的数据:
public class OrderDto
{
public string CustomerName { get; set; }
public decimal Total { get; set; }
}
运用AutoMapper转换:
public void Example()
{
// Complex model
var customer = new Customer
{
Name = "George Costanza"
};
var order = new Order
{
Customer = customer
};
var bosco = new Product
{
Name = "Bosco",
Price = 4.99m
};
order.AddOrderLineItem(bosco, ); // Configure AutoMapper
var config = new MapperConfiguration(cfg => cfg.CreateMap<Order, OrderDto>()); // Perform mapping
var mapper = config.CreateMapper();
OrderDto dto = mapper.Map<Order, OrderDto>(order); dto.CustomerName.ShouldEqual("George Costanza");
dto.Total.ShouldEqual(74.85m);
}
可以看到只要设置下Order和OrderDto之间的类型映射就可以了,我们看OrderDto中的CustomerName和Total属性在领域模型Order中并没有与之相对性,AutoMapper在做解析的时候会按照PascalCase(帕斯卡命名法),CustomerName其实是由Customer+Name 得来的,是AutoMapper的一种映射规则;而Total是因为在Order中有GetTotal()方法,AutoMapper会解析“Get”之后的单词,所以会与Total对应。在编写代码过程中可以运用这种规则来定义名称实现自动转换。
Projection
Projection可以理解为与Flattening相反,Projection是将源对象映射到一个不完全与源对象匹配的目标对象,需要制定自定义成员,如下面的源对象:
public class CalendarEvent
{
public DateTime EventDate { get; set; }
public string Title { get; set; }
}
目标对象:
public class CalendarEventForm
{
public DateTime EventDate { get; set; }
public int EventHour { get; set; }
public int EventMinute { get; set; }
public string Title { get; set; }
}
AutoMapper配置转换代码:
public void Example()
{
// Model
var calendarEvent = new CalendarEvent
{
EventDate = new DateTime(, , , , , ),
Title = "Company Holiday Party"
}; var config = new MapperConfiguration(cfg =>
{
// Configure AutoMapper
cfg.CreateMap<CalendarEvent, CalendarEventForm>()
.ForMember(dest => dest.EventDate, opt => opt.MapFrom(src => src.EventDate.Date))
.ForMember(dest => dest.EventHour, opt => opt.MapFrom(src => src.EventDate.Hour))
.ForMember(dest => dest.EventMinute, opt => opt.MapFrom(src => src.EventDate.Minute));
}); // Perform mapping
var mapper = config.CreateMapper();
CalendarEventForm form = mapper.Map<CalendarEvent, CalendarEventForm>(calendarEvent); form.EventDate.ShouldEqual(new DateTime(, , ));
form.EventHour.ShouldEqual();
form.EventMinute.ShouldEqual();
form.Title.ShouldEqual("Company Holiday Party");
}
Configuration Validation
在进行对象映射的时候,有可能会出现属性名称或者自定义匹配规则不正确而又没有发现的情况,在程序执行时就报错,因此,AutoMapper提供的AssertConfigurationIsValid()方法来验证结构映射是否正确。
config.AssertConfigurationIsValid();如果映射错误,会报“AutoMapperConfigurationException”异常错误,就可以进行调试修改了
Lists and Array
AutoMapper支持的源集合类型包括:
- IEnumerable
- IEnumerable<T>
- ICollection
- ICollection<T>
- IList
- IList<T>
- List<T>
- Arrays
有一种情况是,在使用集合类型类型的时候,类型之间存在继承关系,例如下面我们需要转换的类型:
//源对象
public class ParentSource
{
public int Value1 { get; set; }
} public class ChildSource : ParentSource
{
public int Value2 { get; set; }
} //目标对象
public class ParentDestination
{
public int Value1 { get; set; }
} public class ChildDestination : ParentDestination
{
public int Value2 { get; set; }
}
AutoMapper需要孩子映射的显式配置,AutoMapper配置转换代码:
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<ParentSource, ParentDestination>()
.Include<ChildSource, ChildDestination>();
cfg.CreateMap<ChildSource, ChildDestination>();
}); var sources = new[]
{
new ParentSource(),
new ChildSource(),
new ParentSource()
}; var destinations = config.CreateMapper().Map<ParentSource[], ParentDestination[]>(sources); destinations[].ShouldBeType<ParentDestination>();
destinations[].ShouldBeType<ChildDestination>();
destinations[].ShouldBeType<ParentDestination>();
注意在Initialize初始化CreateMap进行类型映射配置的时候有个Include泛型方法,签名为:“Include this configuration in derived types' maps”,大致意思为包含派生类型中配置,ChildSource是ParentSource的派生类,ChildDestination是ParentDestination的派生类,cfg.CreateMap<ParentSource, ParentDestination>().Include<ChildSource, ChildDestination>(); 这段代码是说明ParentSource和ChildSource之间存在的关系,并且要要显示的配置。
Nested mappings
嵌套对象映射,例如下面的对象:
public class OuterSource
{
public int Value { get; set; }
public InnerSource Inner { get; set; }
} public class InnerSource
{
public int OtherValue { get; set; }
} //目标对象
public class OuterDest
{
public int Value { get; set; }
public InnerDest Inner { get; set; }
} public class InnerDest
{
public int OtherValue { get; set; }
}
AutoMapper配置转换代码:
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<OuterSource, OuterDest>();
cfg.CreateMap<InnerSource, InnerDest>();
});
config.AssertConfigurationIsValid(); var source = new OuterSource
{
Value = ,
Inner = new InnerSource {OtherValue = }
}; var dest = config.CreateMapper().Map<OuterSource, OuterDest>(source); dest.Value.ShouldEqual();
dest.Inner.ShouldNotBeNull();
dest.Inner.OtherValue.ShouldEqual();
对于嵌套映射,只要指定下类型映射关系和嵌套类型映射关系就可以了,也就是这段代码:“Mapper.CreateMap<InnerSource, InnerDest>();” 其实我们在验证类型映射的时候加上Mapper.AssertConfigurationIsValid(); 这段代码看是不是抛出“AutoMapperMappingException”异常来判断类型映射是否正确。
参考资料
关于AutoMapper,陆续更新中...
AutoMapper的介绍与使用(二)的更多相关文章
- AutoMapper.RegExtension 介绍
AutoMapper.RegExtension 为一个特小特小特小的用来根据约定自动调用AutoMapper中的方法配置映射的扩展库.你可以引入该库也可以将源码中核心部分的代码文件夹整个拷贝至项目中. ...
- 从Client应用场景介绍IdentityServer4(二)
原文:从Client应用场景介绍IdentityServer4(二) 本节介绍Client的ClientCredentials客户端模式,先看下画的草图: 一.在Server上添加动态新增Client ...
- c语言学习之基础知识点介绍(十二):结构体的介绍
一.结构体的介绍 /* 语法: struct 结构体名{ 成员列表; }; 切记切记有分号! 说明:成员列表就是指你要保存哪些类型的数据. 注意:上面的语法只是定义一个新的类型,而这个类型叫做结构体类 ...
- Spring 使用介绍(十二)—— Spring Task
一.概述 1.jdk的线程池和任务调用器分别由ExecutorService.ScheduledExecutorService定义,继承关系如下: ThreadPoolExecutor:Executo ...
- (转)OpenStack —— 原理架构介绍(一、二)
原文:http://blog.51cto.com/wzlinux/1961337 http://blog.51cto.com/wzlinux/category18.html-------------O ...
- AutoMapper的介绍与使用(一)
软件环境 vs2015 asp.net mvc 5 .NET Framework 4.5.2 AutoMapper 5.2.0.0 AutoMapper安装 新建asp.net mvc 项目 Auto ...
- SaaS系列介绍之十二: SaaS产品的研发模式
1 产品研发模式慨述 产品研发模式是企业战略的重点.产品研发路线决定了一系列的管理手段和团队建设问题.也是企业的整理策略和经营思路.产品研发模式贯穿着整个产品的生命周期,从市场调研.立项.需求分析.慨 ...
- 微设计(www.weidesigner.com)介绍系列文章(二)
微设计(www.weidesigner.com)是一个专门针对微信公众账号提供营销推广服务而打造的第三方平台. 2.1 怎样注冊微信公众号? 登录mp.weixin.qq.com,点击注冊填写相关信息 ...
- Cordova各个插件使用介绍系列(二)—$cordovaBarcodeScanner扫描二维码与生成二维码
详情链接地址:http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/cordova-2-cordovabarcodescanner/ 这是 ...
随机推荐
- .net 分布式架构之业务消息队列
开源QQ群: .net 开源基础服务 238543768 开源地址: http://git.oschina.net/chejiangyi/Dyd.BusinessMQ ## 业务消息队列 ##业务消 ...
- html5的web存储
在html5标准之前,web存储信息需要cookie来完成,但是cookie不适合大量数据存储.因为需要等待服务器响应,所以速度慢/效率低. 本地存储的特点: localstorage是仅存储在用户的 ...
- css3圆形百分比进度条的实现原理
原文地址:css3圆形百分比进度条的实现原理 今天早上起来在查看jquery插件机制的时候,一不小心点进了css3圆形百分比进度条的相关文章,于是一发不可收拾,开始折腾了... 关于圆形圈的实现,想必 ...
- BPM配置故事之案例1-配置简单流程
某天,Boss找到了信息部工程师小明. Boss:咱们新上了H3 BPM,你研究研究把现在的采购申请流程加上去吧,这是采购申请单. 小明:好嘞 采购申请单 小明回去后拿着表单想了想,开始着手配置. 他 ...
- Android手机相册的布局
实现类似下面的这种布局的方法
- Linux基础介绍【第五篇】
linux权限位 Linux文件或目录的权限位是由9个权限位来控制,每三位为一组,它们分别是文件属主权限.属组权限.其他用户权限. r:read可读权限,对应数字4: w:write可写权限,对应数字 ...
- linux中kvm的安装及快照管理
一.kvm的安装及状态查看 1.安装软件 yum -y install kvm virt-manager libvirt2.启动libvirtd 报错,升级device-mapper-libs yum ...
- Ubuntu手动设置DSL连接
在安装完Ubuntu之后,发现图形界面的DSL连接不管用了,郁闷了好几天,想想移动每个月120个小时的流量岂不是白白浪费了.正当我想重返Windows系统的时候,却发现了手动设置连接DSL的好方法,感 ...
- POJ3693 Maximum repetition substring [后缀数组 ST表]
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9458 Acc ...
- 【repost】JS错误类型的学习
SyntaxError是解析代码时发生的语法错误 // 变量名错误 var 1a; // 缺少括号 console.log 'hello'); (2)ReferenceError Referen ...