AutoMapper 使用总结1
初识AutoMapper
在开始本篇文章之前,先来思考一个问题:一个项目分多层架构,如显示层、业务逻辑层、服务层、数据访问层。层与层访问需要数据载体,也就是类。如果多层通用一个类,一则会暴露出每层的字段,二者会使类字段很多,而且会出现很多冗余字段,这种方式是不可取的;如果每层都使用不同的类,则层与层调用时,一个字段一个字段的赋值又会很麻烦。针对第二种情况,可以使用AutoMapper来帮助我们实现类字段的赋值及转换。
AutoMapper是一个对象映射器,它可以将一个一种类型的对象转换为另一种类型的对象。AutoMapper提供了映射规则及操作方法,使我们不用过多配置就可以映射两个类。
安装AutoMapper
通过Nuget安装AutoMapper,本次使用版本为6.2.2。
AutoMapper配置
初始化
先创建两个类用于映射:
|
1
2
3
4
5
6
7
8
9
10
11
|
public class ProductEntity{ public string Name { get; set; } public decimal Amount { get; set; }}public class ProductDTO{ public string Name { get; set; } public decimal Amount { get; set; }} |
Automapper可以使用静态类和实例方法来创建映射,下面分别使用这两种方式来实现 ProductEntity -> ProductDTO的映射。
- 使用静态方式
|
1
2
|
Mapper.Initialize(cfg => cfg.CreateMap<ProductEntity, ProductDTO>());var productDTO = Mapper.Map<ProductDTO>(productEntity); |
- 使用实例方法
|
1
2
3
|
MapperConfiguration configuration = new MapperConfiguration(cfg => cfg.CreateMap<ProductEntity, ProductDTO>());var mapper = configuration.CreateMapper();var productDTO = mapper.Map<ProductDTO>(productEntity); |
完整的例子:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
[TestMethod]public void TestInitialization(){ var productEntity = new ProductEntity() { Name = "Product" + DateTime.Now.Ticks, Amount = 10 }; Mapper.Initialize(cfg => cfg.CreateMap<ProductEntity, ProductDTO>()); var productDTO = Mapper.Map<ProductDTO>(productEntity); Assert.IsNotNull(productDTO); Assert.IsNotNull(productDTO.Name); Assert.IsTrue(productDTO.Amount > 0);} |
Profiles设置
除了使用以上两总方式类配置映射关系,也可以使用Profie配置来实现映射关系。
创建自定义的Profile需要继承Profile类:
|
1
2
3
4
5
6
7
8
|
public class MyProfile : Profile{ public MyProfile() { CreateMap<ProductEntity, ProductDTO>(); // Other mapping configurations }} |
完成例子:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
[TestMethod]public void TestProfile(){ var productEntity = new ProductEntity() { Name = "Product" + DateTime.Now.Ticks, Amount = 10 }; var configuration = new MapperConfiguration(cfg => cfg.AddProfile<MyProfile>()); var productDTO = configuration.CreateMapper().Map<ProductDTO>(productEntity); Assert.IsNotNull(productDTO); Assert.IsNotNull(productDTO.Name); Assert.IsTrue(productDTO.Amount > 0);} |
除了使用AddProfile,也可以使用AddProfiles添加多个配置;同样,可以同时使用Mapper和Profile,也可以添加多个配置:
|
1
2
3
4
5
|
var configuration = new MapperConfiguration(cfg =>{ cfg.AddProfile<MyProfile>(); cfg.CreateMap<ProductEntity, ProductDTO>();}); |
扁平化映射
AutoMapper先映射名字一致的字段,如果没有,则会尝试使用以下规则来映射:
- 目标中字段去掉前缀“Get”后的部分
- 分割目标字段(根据Pascal命名方式)为单个单词
先创建用到的映射类:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public class Product{ public Supplier Supplier { get; set; } public string Name { get; set; } public decimal GetAmount() { return 10; }}public class Supplier{ public string Name { get; set; }}public class ProductDTO{ public string SupplierName { get; set; } public decimal Amount { get; set; }} |
AutoMapper会自动实现Product.Supplier.Name -> ProductDTO.SupplierName, Product.GetTotal -> ProductDTO.Total的映射。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
[TestMethod]public void TestFalttening(){ var supplier = new Supplier() { Name = "Supplier" + DateTime.Now.Ticks }; var product = new Product() { Supplier = supplier, Name = "Product" + DateTime.Now.Ticks }; Mapper.Initialize(cfg => cfg.CreateMap<Product, ProductDTO>()); var productDTO = Mapper.Map<ProductDTO>(product); Assert.IsNotNull(productDTO); Assert.IsNotNull(productDTO.SupplierName); Assert.IsTrue(productDTO.Amount > 0);} |
集合验证
AutoMapper除了可以映射单个对象外,也可以映射集合对象。AutoMapper源集合类型支持以下几种:
- IEnumerable
- IEnumerable<T>
- ICollection
- ICollection<T>
- IList
- IList<T>
- List<T>
- Arrays
简单类型映射:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public class Source{ public int Value { get; set; }}public class Destination{ public int Value { get; set; }}[TestMethod]public void TestCollectionSimple(){ Mapper.Initialize(cfg => cfg.CreateMap<Source, Destination>()); var sources = new[] { new Source {Value = 1}, new Source {Value = 2}, new Source {Value = 3} }; IEnumerable<Destination> ienumerableDest = Mapper.Map<Source[], IEnumerable<Destination>>(sources); ICollection<Destination> icollectionDest = Mapper.Map<Source[], ICollection<Destination>>(sources); IList<Destination> ilistDest = Mapper.Map<Source[], IList<Destination>>(sources); List<Destination> listDest = Mapper.Map<Source[], List<Destination>>(sources); Destination[] arrayDest = Mapper.Map<Source[], Destination[]>(sources);} |
复杂对象映射:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
public class Order{ private IList<OrderLine> _lineItems = new List<OrderLine>(); public OrderLine[] LineItems { get { return _lineItems.ToArray(); } } public void AddLineItem(OrderLine orderLine) { _lineItems.Add(orderLine); }}public class OrderLine{ public int Quantity { get; set; }}public class OrderDTO{ public OrderLineDTO[] LineItems { get; set; }}public class OrderLineDTO{ public int Quantity { get; set; }}[TestMethod]public void TestCollectionNested(){ Mapper.Initialize(cfg => { cfg.CreateMap<Order, OrderDTO>(); cfg.CreateMap<OrderLine, OrderLineDTO>(); }); var order = new Order(); order.AddLineItem(new OrderLine {Quantity = 10}); order.AddLineItem(new OrderLine {Quantity = 20}); order.AddLineItem(new OrderLine {Quantity = 30}); var orderDTO = Mapper.Map<OrderDTO>(order); Assert.IsNotNull(orderDTO); Assert.IsNotNull(orderDTO.LineItems); Assert.IsTrue(orderDTO.LineItems.Length > 0);} |
投影及条件映射
投影(指定字段)
除了以上使用的自动映射规则,AutoMapper还可以指定映射方式。下面使用ForMemeber指定字段的映射,将一个时间值拆分映射到日期、时、分:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
public class Calendar{ public DateTime CalendarDate { get; set; } public string Title { get; set; }}public class CalendarModel{ public DateTime Date { get; set; } public int Hour { get; set; } public int Minute { get; set; } public string Title { get; set; }}[TestMethod]public void TestProjection(){ var calendar = new Calendar() { Title = "2018年日历", CalendarDate = new DateTime(2018, 1, 1, 11, 59, 59) }; Mapper.Initialize(cfg => cfg .CreateMap<Calendar, CalendarModel>() .ForMember(dest => dest.Date, opt => opt.MapFrom(src =>src.CalendarDate.Date)) .ForMember(dest => dest.Hour, opt => opt.MapFrom(src => src.CalendarDate.Hour)) .ForMember(dest => dest.Minute, opt => opt.MapFrom(src => src.CalendarDate.Minute))); var calendarModel = Mapper.Map<CalendarModel>(calendar); Assert.AreEqual(calendarModel.Date.Ticks, new DateTime(2018, 1, 1).Ticks); Assert.AreEqual(calendarModel.Hour, 11); Assert.AreEqual(calendarModel.Minute, 59);} |
条件映射
有些情况下,我们会考虑添加映射条件,比如,某个值不符合条件时,不允许映射。针对这种情况可以使用ForMember中的Condition:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public class Source{ public int Value { get; set; }}public class Destination{ public uint Value { get; set; }}[TestMethod]public void TestConditionByCondition(){ var source = new Source() { Value = 3 }; //如果Source.Value > 0, 则执行映射;否则,映射失败 Mapper.Initialize(cfg => cfg .CreateMap<Source, Destination>() .ForMember(dest => dest.Value, opt => opt.Condition(src => src.Value > 0))); var destation = Mapper.Map<Destination>(source); //如果不符合条件,则抛出异常 Assert.IsTrue(destation.Value.Equals(3));} |
如果要映射的类符合一定的规则,而且有很多,针对每个类都创建一个CreaterMapper会很麻烦。可以使用AddConditionalObjectMapper指定对象映射规则,这样就不用每个映射关系都添加一个CreateMapper。另外,也可以使用AddMemberConfiguration指定字段的映射规则,比如字段的前后缀:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
public class Product{ public string Name { get; set; } public int Count { get; set; }}public class ProductModel{ public string NameModel { get; set; } public int CountMod { get; set; }}[TestMethod]public void TestConditionByConfiguration(){ var product = new Product() { Name = "Product" + DateTime.Now.Ticks, Count = 10 }; var config = new MapperConfiguration(cfg => { //对象映射规则: 通过以下配置,可以映射所有”目标对象的名称“等于“源对象名称+Model”的类,而不用单个添加CreateMapper映射 cfg.AddConditionalObjectMapper().Where((s, d) => d.Name == s.Name + "Model"); //字段映射规则: 通过以下配置,可以映射“源字段”与“目标字段+Model或Mod”的字段 cfg.AddMemberConfiguration().AddName<PrePostfixName>(_ => _.AddStrings(p => p.DestinationPostfixes, "Model", "Mod")); }); var mapper = config.CreateMapper(); var productModel = mapper.Map<ProductModel>(product); Assert.IsTrue(productModel.CountMod == 10);} |
需要注意的一点是,添加了以上配置,如果目标对象中有字段没有映射到,则会抛出异常。
值转换
如果配置了值转换,AutoMapper会将修改转换后的值以符合配置的规则。比如,配置目标对象中的值添加符号“@@”:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
public class Source{ public string Name { get; set; }}public class Destination{ public string Name { get; set; }}[TestMethod]public void TestValueTransfer(){ var source = new Source() { Name = "Bob" }; Mapper.Initialize(cfg => { cfg.CreateMap<Source, Destination>(); cfg.ValueTransformers.Add<string>(val => string.Format("@{0}@", val)); }); var destation = Mapper.Map<Destination>(source); Assert.AreEqual("@Bob@", destation.Name);} |
空值替换
如果要映射的值为Null,则可以使用NullSubstitute指定Null值的替换值:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public class Source{ public string Name { get; set; }}public class Destination{ public string Name { get; set; }}[TestMethod]public void TestValueTransfer(){ var source = new Source() { }; Mapper.Initialize(cfg => { cfg.CreateMap<Source, Destination>() .ForMember(dest => dest.Name, opt => opt.NullSubstitute("其他值")); }); var destation = Mapper.Map<Destination>(source); Assert.AreEqual("其他值", destation.Name);} |
配置验证及设置
配置了映射,但是如何确定是否映射成功或者是否有字段没有映射呢?可以添加Mapper.AssertConfigurationIsValid();来验证是否映射成功。默认情况下,目标对象中的字段都被映射到后,AssertConfigurationIsValid才会返回True。也就是说,源对象必须包含所有目标对象,这样在大多数情况下不是我们想要的,我们可以使用下面的方法来指定验证规则:
- 指定单个字段不验证
- 指定整个Map验证规则
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
public class Product{ public string Name { get; set; } public int Amount { get; set; }}public class ProductModel{ public string Name { get; set; } public int Amount { get; set; } public string ViewName { get; set; }}public class ProductDTO{ public string Name { get; set; } public int Amount { get; set; } public string ViewName { get; set; }}[TestMethod]public void TestValidation(){ var product = new Product() { Name = "Product" + DateTime.Now.Ticks, Amount = 10 }; Mapper.Initialize(cfg => { //1. 指定字段映射方式 cfg.CreateMap<Product, ProductModel>() .ForMember(dest => dest.ViewName, opt => opt.Ignore()); //如果不添加此设置,会抛出异常 //2. 指定整个对象映射方式 //MemberList: // Source: 检查源对象所有字段映射成功 // Destination:检查目标对象所有字段映射成功 // None: 跳过验证 cfg.CreateMap<Product, ProductDTO>(MemberList.Source); }); var productModel = Mapper.Map<ProductModel>(product); var productDTO = Mapper.Map<ProductDTO>(product); //验证映射是否成功 Mapper.AssertConfigurationIsValid();} |
设置转换前后行为
有的时候你可能会在创建映射前后对数据做一些处理,AutoMapper就提供了这种方式:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
public class Source{ public string Name { get; set; } public int Value { get; set; }}public class Destination{ public string Name { get; set; } public int Value { get; set; }}[TestMethod]public void TestBeforeOrAfter(){ var source = new Source() { Name = "Product" + DateTime.Now.Ticks, }; Mapper.Initialize(cfg => { cfg.CreateMap<Source, Destination>() .BeforeMap((src, dest) => src.Value = src.Value + 10) .AfterMap((src, dest) => dest.Name = "Pobin"); }); var productModel = Mapper.Map<Destination>(source); Assert.AreEqual("Pobin", productModel.Name);} |
反向映射
从6.1.0开始,AutoMapper通过调用Reverse可以实现反向映射。反向映射根据初始化时创建的正向映射规则来做反向映射:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
public class Order{ public decimal Total { get; set; } public Customer Customer { get; set; }}public class Customer{ public string Name { get; set; }}public class OrderDTO{ public decimal Total { get; set; } public string CustomerName { get; set; }}[TestMethod]public void TestReverseMapping(){ var customer = new Customer { Name = "Tom" }; var order = new Order { Customer = customer, Total = 20 }; Mapper.Initialize(cfg => { cfg.CreateMap<Order, OrderDTO>() .ForMember(dest => dest.CustomerName, opt => opt.MapFrom(src => src.Customer.Name)) //正向映射规则 .ReverseMap(); //设置反向映射 }); //正向映射 var orderDTO = Mapper.Map<OrderDTO>(order); //反向映射:使用ReverseMap,不用再创建OrderDTO -> Order的映射,而且还能保留正向的映射规则 var orderConverted = Mapper.Map<Order>(orderDTO); Assert.IsNotNull(orderConverted.Customer); Assert.AreEqual("Tom", orderConverted.Customer.Name);} |
如果反向映射中不想使用原先的映射规则,也可以取消掉:
|
1
2
3
4
5
6
|
Mapper.Initialize(cfg => { cfg.CreateMap<Order, OrderDTO>() .ForMember(dest => dest.CustomerName, opt => opt.MapFrom(src => src.Customer.Name)) //正向映射规则 .ReverseMap() .ForPath(src => src.Customer.Name, opt => opt.Ignore()); //设置反向映射}); |
自定义转换器
有些情况下目标字段类型和源字段类型不一致,可以通过类型转换器实现映射,类型转换器有三种实现方式:
|
1
2
3
|
void ConvertUsing(Func<TSource, TDestination> mappingFunction);void ConvertUsing(ITypeConverter<TSource, TDestination> converter);void ConvertUsing<TTypeConverter>() where TTypeConverter : ITypeConverter<TSource, TDestination>; |
下面通过一个例子来演示下以上三种类型转换器的使用方式:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
namespace AutoMapperSummary{ [TestClass] public class CustomerTypeConvert { public class Source { public string Value1 { get; set; } public string Value2 { get; set; } public string Value3 { get; set; } } public class Destination { public int Value1 { get; set; } public DateTime Value2 { get; set; } public Type Value3 { get; set; } } public class DateTimeTypeConverter : ITypeConverter<string, DateTime> { public DateTime Convert(string source, DateTime destination, ResolutionContext context) { return System.Convert.ToDateTime(source); } } public class TypeTypeConverter : ITypeConverter<string, Type> { public Type Convert(string source, Type destination, ResolutionContext context) { return Assembly.GetExecutingAssembly().GetType(source); } } [TestMethod] public void TestTypeConvert() { var config = new MapperConfiguration(cfg => { cfg.CreateMap<string, int>().ConvertUsing((string s) => Convert.ToInt32(s)); cfg.CreateMap<string, DateTime>().ConvertUsing(new DateTimeTypeConverter()); cfg.CreateMap<string, Type>().ConvertUsing<TypeTypeConverter>(); cfg.CreateMap<Source, Destination>(); }); config.AssertConfigurationIsValid(); //验证映射是否成功 var source = new Source { Value1 = "20", Value2 = "2018/1/1", Value3 = "AutoMapperSummary.CustomerTypeConvert+Destination" }; var mapper = config.CreateMapper(); var destination = mapper.Map<Source, Destination>(source); Assert.AreEqual(typeof(Destination), destination.Value3); } }} |
自定义解析器
使用AutoMapper的自带解析规则,我们可以很方便的实现对象的映射。比如:源/目标字段名称一致,“Get/get + 源字段“与"目标字段"一致等。除了这些简单的映射,还可以使用ForMember指定字段映射。但是,某些情况下,解析规则会很复杂,使用自带的解析规则无法实现。这时可以自定义解析规则,可以通过以下三种方式使用自定义的解析器:
|
1
2
3
|
ResolveUsing<TValueResolver>ResolveUsing(typeof(CustomValueResolver))ResolveUsing(aValueResolverInstance) |
下面通过一个例子来演示如何使用自定义解析器:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
public class Source{ public string FirstName { get; set; } public string LastName { get; set; }}public class Destination{ public string Name { get; set; }}/// <summary>/// 自定义解析器: 组合姓名/// </summary>public class CustomResolver : IValueResolver<Source, Destination, string>{ public string Resolve(Source source, Destination destination, string destMember, ResolutionContext context) { if (source != null && !string.IsNullOrEmpty(source.FirstName) && !string.IsNullOrEmpty(source.LastName)) { return string.Format("{0} {1}", source.FirstName, source.LastName); } return string.Empty; }}[TestMethod]public void TestResolver(){ Mapper.Initialize(cfg => cfg.CreateMap<Source, Destination>() .ForMember(dest => dest.Name, opt => opt.ResolveUsing<CustomResolver>())); Mapper.AssertConfigurationIsValid(); var source = new Source { FirstName = "Michael", LastName = "Jackson" }; var destination = Mapper.Map<Source, Destination>(source); Assert.AreEqual("Michael Jackson", destination.Name);} |
AutoMapper封装
AutoMapper功能很强大,自定义配置支持也非常好,但是真正项目中使用时却很少用到这么多功能,而且一般都会对AutoMapper进一步封装使用。一方面使用起来方面,另外一方面也可以使代码统一。下面的只是做一个简单的封装,还需要结合实际项目使用:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
/// <summary> /// AutoMapper帮助类 /// </summary> public class AutoMapperManager { private static readonly MapperConfigurationExpression MapperConfiguration = new MapperConfigurationExpression(); static AutoMapperManager() { } private AutoMapperManager() { AutoMapper.Mapper.Initialize(MapperConfiguration); } public static AutoMapperManager Instance { get; } = new AutoMapperManager(); /// <summary> /// 添加映射关系 /// </summary> /// <typeparam name="TSource"></typeparam> /// <typeparam name="TDestination"></typeparam> public void AddMap<TSource, TDestination>() where TSource : class, new() where TDestination : class, new() { MapperConfiguration.CreateMap<TSource, TDestination>(); } /// <summary> /// 获取映射值 /// </summary> /// <typeparam name="TDestination"></typeparam> /// <param name="source"></param> /// <returns></returns> public TDestination Map<TDestination>(object source) where TDestination : class, new() { if (source == null) { return default(TDestination); } return Mapper.Map<TDestination>(source); } /// <summary> /// 获取集合映射值 /// </summary> /// <typeparam name="TDestination"></typeparam> /// <param name="source"></param> /// <returns></returns> public IEnumerable<TDestination> Map<TDestination>(IEnumerable source) where TDestination : class, new() { if (source == null) { return default(IEnumerable<TDestination>); } return Mapper.Map<IEnumerable<TDestination>>(source); } /// <summary> /// 获取映射值 /// </summary> /// <typeparam name="TSource"></typeparam> /// <typeparam name="TDestination"></typeparam> /// <param name="source"></param> /// <returns></returns> public TDestination Map<TSource, TDestination>(TSource source) where TSource : class, new () where TDestination : class, new() { if (source == null) { return default(TDestination); } return Mapper.Map<TSource, TDestination>(source); } /// <summary> /// 获取集合映射值 /// </summary> /// <typeparam name="TSource"></typeparam> /// <typeparam name="TDestination"></typeparam> /// <param name="source"></param> /// <returns></returns> public IEnumerable<TDestination> Map<TSource, TDestination>(IEnumerable<TSource> source) where TSource : class, new() where TDestination : class, new() { if (source == null) { return default(IEnumerable<TDestination>); } return Mapper.Map<IEnumerable<TSource>, IEnumerable<TDestination>>(source); } /// <summary> /// 读取DataReader内容 /// </summary> /// <typeparam name="TDestination"></typeparam> /// <param name="reader"></param> /// <returns></returns> public IEnumerable<TDestination> Map<TDestination>(IDataReader reader) { if (reader == null) { return new List<TDestination>(); } var result = Mapper.Map<IEnumerable<TDestination>>(reader); if (!reader.IsClosed) { reader.Close(); } return result; } } |
总结
本篇文章列举了AutoMapper的基本使用方式,更多的使用可以参考官方文档:http://automapper.readthedocs.io/en/latest/index.html
AutoMapper 使用总结1的更多相关文章
- 恋爱虽易,相处不易:当EntityFramework爱上AutoMapper
剧情开始 为何相爱? 相处的问题? 女人的伟大? 剧情收尾? 有时候相识即是一种缘分,相爱也不需要太多的理由,一个眼神足矣,当EntityFramework遇上AutoMapper,就是如此,恋爱虽易 ...
- 【AutoMapper官方文档】DTO与Domin Model相互转换(上)
写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...
- AutoMapper
什么是AutoMapper? AutoMapper是一个对象和对象间的映射器.对象与对象的映射是通过转变一种类型的输入对象为一种不同类型的输出对象工作的.让AutoMapper有意思的地方在于它提供了 ...
- AutoMapper随笔记
平台之大势何人能挡? 带着你的Net飞奔吧! http://www.cnblogs.com/dunitian/p/4822808.html#skill 先看效果:(完整Demo:https://git ...
- AutoMapper:Unmapped members were found. Review the types and members below. Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
异常处理汇总-后端系列 http://www.cnblogs.com/dunitian/p/4523006.html 应用场景:ViewModel==>Mode映射的时候出错 AutoMappe ...
- AutoMapper的介绍与使用(一)
软件环境 vs2015 asp.net mvc 5 .NET Framework 4.5.2 AutoMapper 5.2.0.0 AutoMapper安装 新建asp.net mvc 项目 Auto ...
- AutoMapper使用中的问题
指定值只会执行一次 public class MomanBaseProfile : Profile { public MomanBaseProfile() { CreateMap<Request ...
- 【AutoMapper官方文档】DTO与Domin Model相互转换(中)
写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...
- 【AutoMapper官方文档】DTO与Domin Model相互转换(下)
写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...
- 【道德经】漫谈实体、对象、DTO及AutoMapper的使用
写在前面 实体和值对象 实体和对象 故常无欲以观其妙,常有欲以观其徼 初始实体和演化实体 代码中的DTO AutoMapper实体转换 后记 实体(Entity).对象(Object).DTO(Dat ...
随机推荐
- iOS 应用打包 设备兼容性问题(Build Active Architecture Only)
在把应用打包安装到iPod Touch上面时,设备提示不兼容,所以就有几种猜想: 1.CPU架构问题,因为我手里这个iPod Touch的CPU是A5,是32位的: 2.TARGETS里面相关的设置对 ...
- ACM数论-求组合数
我们利用这个公式求阶乘和逆元求阶: #include<cstdio> const int N = 200000 + 5; const int MOD = (int)1e9 + 7; int ...
- Apple Tree POJ - 2486
Apple Tree POJ - 2486 题目大意:一棵点带权有根树,根节点为1.从根节点出发,走k步,求能收集的最大权值和. 树形dp.复杂度可能是O(玄学),不会超过$O(nk^2)$.(反正这 ...
- ACM_跳坑小能手(暴力)
跳坑小能手 Time Limit: 2000/1000ms (Java/Others) Problem Description: GDUFE-GAME现场有一个游戏场地人头窜动,围观参与游戏的学生在场 ...
- ACM_最小公倍数
Lowest Common Multiple Plus Time Limit: 2000/1000ms (Java/Others) Problem Description: 求n个数的最小公倍数. I ...
- Create the first sql server 2016 mobile report;创建 第一个 sqlserver 2016 Mobile report
在微软收购了datazen之后,sqlserver2016 集成了mobilereport,mobile report 基于html5,兼容各类主流浏览器,之前ssrs2008 R2中很多chart类 ...
- CentOS7.5搭建LAMP环境
导言 LAMP环境搭建,网上可以搜到很多的结果.为什么我还要整理一下呢,是因为有些网上给出的解决办法可能仅适用于某些特定的环境下,并不一定适用于所有出现问题的情况. 当然我写本篇的目的也不是保证所有的 ...
- 关于NSCELL
作为一个初学者,我一直很弄不明白NSCell的子类,比如,NSButtonCell,NSImageCell及其对应的控件之间的关系.今天,在做一个TableView实现的时候,我终于开始有点悟了——好 ...
- 结对项目--黄金点游戏(邓乐&曾亮)
#include<stdio.h> #include<stdlib.h> #include<Windows.h> int result[100][1000000]; ...
- android手机web网站拨打电话几种方式
1. <input name="phone" format="*m" value="13"/> <do type=&quo ...