经过上一篇博客的学习,大体了解了Auto Mapper的运行机制和操作流程。我们下来学习下,AutoMapper里面具体的一些东西。
一:规则
当我们使用AutoMapper创建实体和外部Model的映射的时候,AutoMapper的匹配原值有三种方式。
#:名称相同的属性进行映射,不区分大小写。
#:带Get前缀的方法进行映射。<例子(Order和OrderDto):Order中的GetTotal分割成Get和Total,Total会和Dto中的进行匹配。>
#:目标类型属性分割。
Order类
/// <summary> /// 订单 /// </summary> public class Order { public Customer Customer { get; set; } public decimal GetTotal() { return 10*10; } } /// <summary> /// 顾客 /// </summary> public class Customer { public string Name { get; set; } }
OrderDto类
/// <summary> /// 数据传输对象Dto /// </summary> public class OrderDto { public string CustomerName { get; set; } public decimal Total { get; set; } }
这里我们将Order转换为OrderDto,也就是Order里面的Customer中的Name转换为CustomerName;
Order dto=new Order() { Customer = new Customer{Name = "ahui"}, }; //配置 Mapper.CreateMap<Order, OrderDto>(); //执行 var order = Mapper.Map<Order,OrderDto>(dto); Console.WriteLine(order.CustomerName); Console.ReadKey();
二:AutoMapper中利用Condition来进行判断,从而选择是否进行转换。
订单
/// <summary> /// 订单 /// </summary> public class Order { public Order() { Number = 100; } //订单数量 public int Number { get; set; } }
订单DTO
/// <summary> /// 数据传输对象Dto /// </summary> public class OrderDto { public OrderDto() { Num = 90; } public int Num { get; set; } }
Main()方法
//配置 通过Condition来规定Order中的值是0~12之间。在这个之间就可以进行映射,不是就不映射。输出其默认值10; Mapper.CreateMap<Order,OrderDto>().ForMember(x=>x.Num,mo=>mo.Condition(s=>s.Number >0&& s.Number <12)).ForMember(x=>x.Num,mo=>mo.MapFrom(x=>x.Number)); //执行映射 var orderDto = Mapper.Map<OrderDto>(new Order(){Number = 10}); var p1 = Mapper.Map<OrderDto>(new Order(){Number = 20}); Console.WriteLine(orderDto.Num); //这里输出10 Console.WriteLine(p1.Num); //这里转换失败,结果为90. Console.ReadKey();
<a href="http://images2015.cnblogs.com/blog/679140/201603/679140-20160324203534933-1213841617.png" rel="noopener"><img style="background-image: none; padding-top: 0; padding-left: 0; margin: 0; display: inline; padding-right: 0; border-width: 0" title="image" src="https://images2015.cnblogs.com/blog/679140/201603/679140-20160324203535683-1107665481.png" alt="image" width="244" height="52" border="0"></a>
通过Condition这个方法我们可以规定如何去转换,指定转换条件。
三:通过Initialize来增加一个配置文件。
这里增加一个配置文件,主要是防止我们以后配置文件多了,我们不必每一次都写,在需要调用配置文件即可。
1:新建一个ProFilesMapper类继承自Profile,并且实现他的方法Configuer(),这个方法就是我们在里面写配置文件的。
/// <summary> /// 配置文件 /// </summary> public class ProFilesMapper:Profile { protected override void Configure() { //这里放一些CreateMap(),也就是我们之前的配置映射 //配置 通过Condition来规定Order中的值是0~12之间。在这个之间就可以进行映射,不是就不映射。输出其默认值10; Mapper.CreateMap<Order, OrderDto>().ForMember(x => x.Num, mo => mo.Condition(s => s.Number > 0 && s.Number < 12)).ForMember(x => x.Num, mo => mo.MapFrom(x => x.Number)); } }
2:在main()方法里面可以直接使用加载配置文件就可以实现之前的的配置了。
//配置 Mapper.Initialize(x =>x.AddProfile<ProFilesMapper>());
这样就可以实现配置了。
//配置 Mapper.Initialize(x =>x.AddProfile<ProFilesMapper>()); //执行映射 var orderDto = Mapper.Map<OrderDto>(new Order() { Number = 10 }); var p1 = Mapper.Map<OrderDto>(new Order() { Number = 20 }); Console.WriteLine(orderDto.Num); //这里输出10 Console.WriteLine(p1.Num); //这里转换失败,结果为90. Console.ReadKey();
四:实现命名惯例
只需要配置中添加下面两句代码
protected override void Configure() { //这里放一些CreateMap(),也就是我们之前的配置映射 //配置 通过Condition来规定Order中的值是0~12之间。在这个之间就可以进行映射,不是就不映射。输出其默认值10; Mapper.CreateMap<Order, OrderDto>().ForMember(x => x.Num, mo => mo.Condition(s => s.Number > 0 && s.Number < 12)).ForMember(x => x.Num, mo => mo.MapFrom(x => x.Number)); //通过下面的两个设置源和目标的命名惯例 而且必须写在CreateMap后面 SourceMemberNamingConvention=new LowerUnderscoreNamingConvention(); DestinationMemberNamingConvention=new PascalCaseNamingConvention(); }
//配置 Mapper.Initialize(x=>x.AddProfile<ProFilesMapper>()); //执行映射 var d1 = Mapper.Map<OrderDto>(new Order() { MyName ="ahui" }); Console.WriteLine(d1.my_name); Console.ReadKey();
看下我们的两个属性
public string my_name { get; set; }
public string MyName { get; set; }
这个我觉得就是像忽略了大小写,直接就可以进行映射。
五:集合之间的映射
这里就是在我们Mapper.Map<>(),执行映射的时候,这里我们看他们需要什么类型的,就传递什么。
配置:
Mapper.CreateMap<Souce,Destination>();
类代码:
public class Souce { public int Value { get; set; } } public class Destination { public int Value { get; set; } }
main()方法:
#region 示例08 //配置 Mapper.Initialize(x=>x.AddProfile<ProFilesMapper>()); //初始化,这就是将其初始化为数组 var sources = new[] { new Souce(){Value = 1}, new Souce(){Value = 2}, new Souce(){Value = 3}, }; //执行映射 IEnumerable<Destination> iEnumerabledDestinations = Mapper.Map<IEnumerable<Destination>>(sources); ICollection<Destination> iCollectionDestinations = Mapper.Map<ICollection<Destination>>(sources); IList<Destination> iListDest = Mapper.Map<IList<Destination>>(sources); List<Destination> listDests = Mapper.Map<List<Destination>>(sources); Destination[] deatArrey = Mapper.Map<Destination[]>(sources); Console.WriteLine("******第一个转换*****"); foreach (var item in iEnumerabledDestinations) { Console.WriteLine(item.Value + ",,"); } Console.WriteLine("******第二个转换*****"); foreach (var item in iCollectionDestinations) { Console.WriteLine(item.Value + ",,"); } Console.WriteLine("******第三个转换*****"); foreach (var item in iListDest) { Console.WriteLine(item.Value + ",,"); } Console.WriteLine("******第四个转换*****"); foreach (var item in deatArrey) { Console.WriteLine(item.Value + ",,"); } Console.ReadKey();
我们通过这四种类型的执行映射都可以得到我们想要的结果,说明AutoMapper是成功的。