安装方式:使用vs自带的nuget管理工具,搜索AutoMapper ,选择第一个安装到你的项目即可。

我从网上找了一些资料,

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

参考网址:http://blog.csdn.net/csethcrm/article/details/52934325

下载了个demo,然后自己又写了一遍,我把AutoMapper 的使用分为两种:

1、viewmodel与实体的字段名字是一致的,viewmodel的字段可以与实体中的字段数量不一致。 

还有一种情况是:源实体中的字段名字是Getxxx,那么viewmodel中对应的字段可以是xxx,也会自动对应赋值,比如我写的demo中源实体中GetA,viewmodel中的A;

再有一种情况就是实体中的实体赋值,在我写的这个例子中,源实体中包含的实体类字段为Sub,里面包含的字段名字为Age,

那么destmodel中对应的字段名字可以是:SubAge,那么automapper就可以自动为你赋值了,大家看最后的运行结果。

给大家看下我建的源实体:

c# AutoMapper 使用方式和再封装 随笔 第1张
    public class Source1 { public string Name { set; get; } public string GetA { set; get; }
public string GetD { set; get; } public string SetB { set; get; } public string c { set; get; } public SubSource1 Sub { set; get; } } public class SubSource1 { public string Age { set; get; } }
c# AutoMapper 使用方式和再封装 随笔 第2张

还有viewmodel(要转化成为你想要的模型):

c# AutoMapper 使用方式和再封装 随笔 第3张
    public class Dest1 { public string Name { set; get; } public string A { set; get; } public string C { set; get; } public string SubAge { set; get; } public string D { set; get; } }
c# AutoMapper 使用方式和再封装 随笔 第4张

我封装的扩展方法:

 

c# AutoMapper 使用方式和再封装 随笔 第5张
        /// <summary>
        /// 类型映射,默认字段名字一一对应 /// </summary>
        /// <typeparam name="TDestination">转化之后的model,可以理解为viewmodel</typeparam>
        /// <typeparam name="TSource">要被转化的实体,Entity</typeparam>
        /// <param name="source">可以使用这个扩展方法的类型,任何引用类型</param>
        /// <returns>转化之后的实体</returns>
        public static TDestination MapTo<TDestination, TSource>(this TSource source) where TDestination : class
            where TSource : class { if (source == null) return default(TDestination); var config = new MapperConfiguration(cfg => cfg.CreateMap<TSource, TDestination>()); var mapper = config.CreateMapper(); return mapper.Map<TDestination>(source); }
c# AutoMapper 使用方式和再封装 随笔 第6张

  

使用方式:

c# AutoMapper 使用方式和再封装 随笔 第7张
                var source1 = new Source1 { Name = "source", Sub = new SubSource1 { Age = "25" }, c = "c", GetA = "A", SetB = "B" }; var destViewModel = source1.MapTo<Source1,Dest1>();
c# AutoMapper 使用方式和再封装 随笔 第8张

运行结果:

c# AutoMapper 使用方式和再封装 随笔 第9张

 

 

2.viewmodel与实体字段名字没有全部对应,只有几个字段的名字和源实体中的字段名字是一样的,其他的字段是通过实体中的几个字段组合或者是格式或者是类型转化而来的,

使用方法:不能再使用这个扩展方法了,只能自己额外写代码,代码如下:

c# AutoMapper 使用方式和再封装 随笔 第10张
               var config2 = new MapperConfiguration( cfg => cfg.CreateMap<SourceUser, DestUser2>() .ForMember(d => d.DestName, opt => opt.MapFrom(s => s.Name))    //指定字段一一对应
                        .ForMember(d => d.Birthday, opt => opt.MapFrom(src => src.Birthday.ToString("yy-MM-dd HH:mm")))//指定字段,并转化指定的格式
                        .ForMember(d => d.Age, opt => opt.Condition(src => src.Age > 5))//条件赋值
                        .ForMember(d => d.A1, opt => opt.Ignore())//忽略该字段,不给该字段赋值
                        .ForMember(d => d.A1, opt => opt.NullSubstitute("Default Value"))//如果源字段值为空,则赋值为 Default Value
                        .ForMember(d => d.A1, opt => opt.MapFrom(src => src.Name + src.Age * 3 + src.Birthday.ToString("d"))));//可以自己随意组合赋值
                var mapper2 = config2.CreateMapper();
c# AutoMapper 使用方式和再封装 随笔 第11张

注释中都包含了平时常用的几种情况,其他的我就没有再写。

下面再给大家把list转化的扩展方法代码贴上:

 

c# AutoMapper 使用方式和再封装 随笔 第12张
        /// <summary>
        /// 集合列表类型映射,默认字段名字一一对应 /// </summary>
        /// <typeparam name="TDestination">转化之后的model,可以理解为viewmodel</typeparam>
        /// <typeparam name="TSource">要被转化的实体,Entity</typeparam>
        /// <param name="source">可以使用这个扩展方法的类型,任何引用类型</param>
        /// <returns>转化之后的实体列表</returns>
        public static IEnumerable<TDestination> MapToList<TSource,TDestination>(this IEnumerable<TSource> source) where TDestination : class
            where TSource : class { if (source == null) return new List<TDestination>(); var config = new MapperConfiguration(cfg => cfg.CreateMap<TSource, TDestination>()); var mapper = config.CreateMapper(); return mapper.Map<List<TDestination>>(source); }
c# AutoMapper 使用方式和再封装 随笔 第13张

  

同样的使用方式:

c# AutoMapper 使用方式和再封装 随笔 第14张
                var source1 = new Source1 { Name = "source", Sub = new SubSource1 { Age = "25" }, c = "c", GetA = "A", SetB = "B" };           var source3 = new Source1 { Name = "source3", Sub = new SubSource1 { Age = "253" }, c = "c3", GetA = "A3", SetB = "B3" }; var sourceList = new List<Source1> { source1, source3 }; var destViewModelList = sourceList.MapToList<Source1,Dest1>();
c# AutoMapper 使用方式和再封装 随笔 第15张

运行结果:

c# AutoMapper 使用方式和再封装 随笔 第16张

 

 

以上就是我个人所得,如有错误,欢迎大家指正。

 

//2017.12.4 修改:destination和source写反了,导致我的总结有些错误,现在纠正一下:错误结论已经红色标注,中间的截图也换成正确的了,工具类方法也已经修正。

 

出处:https://www.cnblogs.com/dawenyang/p/7966850.html

===========================================================

一、最简单的用法

有两个类User和UserDto

c# AutoMapper 使用方式和再封装 随笔 第17张
 1     public class User
 2     {
 3         public int Id { get; set; }
 4         public string Name { get; set; }
 5         public int Age { get; set; }
 6     }
 7 
 8     public class UserDto
 9     {
10         public string Name { get; set; }
11         public int Age { get; set; }
12     }
c# AutoMapper 使用方式和再封装 随笔 第18张

将User转换成UserDto也和简单

c# AutoMapper 使用方式和再封装 随笔 第19张
1     Mapper.Initialize(x => x.CreateMap<User, UserDto>());
2     User user = new User()
3     {
4         Id = 1,
5         Name = "caoyc",
6         Age = 20
7     };
8     var dto = Mapper.Map<UserDto>(user);
c# AutoMapper 使用方式和再封装 随笔 第20张

 这是一种最简单的使用,AutoMapper会更加字段名称去自动对于,忽略大小写。

 

二、如果属性名称不同

将UserDto的Name属性改成Name2

c# AutoMapper 使用方式和再封装 随笔 第21张
 1     Mapper.Initialize(x => 
 2         x.CreateMap<User, UserDto>()
 3          .ForMember(d =>d.Name2, opt => {
 4             opt.MapFrom(s => s.Name);
 5             })
 6         );
 7 
 8     User user = new User()
 9     {
10         Id = 1,
11         Name = "caoyc",
12         Age = 20
13     };
14 
15     var dto = Mapper.Map<UserDto>(user);
c# AutoMapper 使用方式和再封装 随笔 第22张

c# AutoMapper 使用方式和再封装 随笔 第23张

 

三、使用Profile配置

自定义一个UserProfile类继承Profile,并重写Configure方法

c# AutoMapper 使用方式和再封装 随笔 第24张
 1     public class UserProfile : Profile
 2     {
 3         protected override void Configure()
 4         {
 5             CreateMap<User, UserDto>()
 6                 .ForMember(d => d.Name2, opt =>
 7                 {
 8                     opt.MapFrom(s => s.Name);
 9                 });
10         }
11     }
c# AutoMapper 使用方式和再封装 随笔 第25张

使用时就这样

c# AutoMapper 使用方式和再封装 随笔 第26张
 1     Mapper.Initialize(x => x.AddProfile<UserProfile>());
 2 
 3     User user = new User()
 4     {
 5         Id = 1,
 6         Name = "caoyc",
 7         Age = 20
 8     };
 9 
10     var dto = Mapper.Map<UserDto>(user);
c# AutoMapper 使用方式和再封装 随笔 第27张

 

四、空值替换NullSubstitute

空值替换允许我们将Source对象中的空值在转换为Destination的值的时候,使用指定的值来替换空值。

c# AutoMapper 使用方式和再封装 随笔 第28张
 1     public class UserProfile : Profile
 2     {
 3         protected override void Configure()
 4         {
 5             CreateMap<User, UserDto>()
 6                 .ForMember(d => d.Name2, opt => opt.MapFrom(s => s.Name))
 7                 .ForMember(d => d.Name2, opt => opt.NullSubstitute("值为空"));
 8                 
 9         }
10     }
c# AutoMapper 使用方式和再封装 随笔 第29张 c# AutoMapper 使用方式和再封装 随笔 第30张
1     Mapper.Initialize(x => x.AddProfile<UserProfile>());
2 
3     User user = new User()
4     {
5         Id = 1,
6         Age = 20
7     };
8 
9     var dto = Mapper.Map<UserDto>(user);
c# AutoMapper 使用方式和再封装 随笔 第31张

结果为:

c# AutoMapper 使用方式和再封装 随笔 第32张

 

五、忽略属性Ignore

c# AutoMapper 使用方式和再封装 随笔 第33张
 1     public class User
 2     {
 3         public int Id { get; set; }
 4         public string Name { get; set; }
 5         public int Age { get; set; }
 6     }
 7 
 8     public class UserDto
 9     {
10         public string Name { get; set; }
11         public int Age { get; set; }
12 
13     }
14 
15     public class UserProfile : Profile
16     {
17         protected override void Configure()
18         {
19             CreateMap<User, UserDto>().ForMember("Name", opt => opt.Ignore());
20         }
21     }
c# AutoMapper 使用方式和再封装 随笔 第34张

使用

c# AutoMapper 使用方式和再封装 随笔 第35张
 1     Mapper.Initialize(x => x.AddProfile<UserProfile>());
 2 
 3     User user = new User()
 4     {
 5         Id = 1,
 6         Name="caoyc",
 7         Age = 20
 8     };
 9 
10     var dto = Mapper.Map<UserDto>(user);
c# AutoMapper 使用方式和再封装 随笔 第36张

结果:

c# AutoMapper 使用方式和再封装 随笔 第37张

 

六、预设值

如果目标属性多于源属性,可以进行预设值

c# AutoMapper 使用方式和再封装 随笔 第38张
 1     public class User
 2     {
 3         public int Id { get; set; }
 4         public string Name { get; set; }
 5         public int Age { get; set; }
 6     }
 7 
 8     public class UserDto
 9     {
10         public string Name { get; set; }
11         public int Age { get; set; }
12         public string Gender { get; set; }
13 
14     }
15 
16     public class UserProfile : Profile
17     {
18         protected override void Configure()
19         {
20             CreateMap<User, UserDto>();
21         }
22     }
c# AutoMapper 使用方式和再封装 随笔 第39张

使用

c# AutoMapper 使用方式和再封装 随笔 第40张
 1     Mapper.Initialize(x => x.AddProfile<UserProfile>());
 2 
 3     User user = new User()
 4     {
 5         Id = 1,
 6         Name="caoyc",
 7         Age = 20
 8     };
 9 
10     UserDto dto = new UserDto() {Gender = ""};
11     Mapper.Map(user, dto);
c# AutoMapper 使用方式和再封装 随笔 第41张

c# AutoMapper 使用方式和再封装 随笔 第42张

 七、类型转换ITypeConverter

如果数据中Gender存储的int类型,而DTO中Gender是String类型

c# AutoMapper 使用方式和再封装 随笔 第43张
1     public class User
2     {
3         public int Gender { get; set; }
4     }
5 
6     public class UserDto
7     {
8         public string Gender { get; set; }
9     }
c# AutoMapper 使用方式和再封装 随笔 第44张

类型转换类,需要实现接口ITypeConverter

c# AutoMapper 使用方式和再封装 随笔 第45张
 1     public class GenderTypeConvertert : ITypeConverter<int, string>
 2     {
 3         public string Convert(int source, string destination, ResolutionContext context)
 4         {
 5             switch (source)
 6             {
 7                 case 0:
 8                     destination = "";
 9                     break;
10                 case 1:
11                     destination = "";
12                     break;
13                 default:
14                     destination = "未知";
15                     break;
16             }
17             return destination;
18         }
19     }
c# AutoMapper 使用方式和再封装 随笔 第46张

配置规则

c# AutoMapper 使用方式和再封装 随笔 第47张
 1     public class UserProfile : Profile
 2     {
 3         protected override void Configure()
 4         {
 5             CreateMap<User, UserDto>();
 6 
 7             CreateMap<int, string>().ConvertUsing<GenderTypeConvertert>();
 8             //也可以写这样
 9             //CreateMap<int, string>().ConvertUsing(new GenderTypeConvertert());
10         }
11     }
c# AutoMapper 使用方式和再封装 随笔 第48张

使用

c# AutoMapper 使用方式和再封装 随笔 第49张
 1     Mapper.Initialize(x => x.AddProfile<UserProfile>());
 2 
 3     User user0 = new User() { Gender = 0 };
 4     User user1 = new User() { Gender = 1 };
 5     User user2 = new User() { Gender = 2 };
 6     var dto0= Mapper.Map<UserDto>(user0);
 7     var dto1 = Mapper.Map<UserDto>(user1);
 8     var dto2 = Mapper.Map<UserDto>(user2);
 9 
10     Console.WriteLine("dto0:{0}", dto0.Gender);
11     Console.WriteLine("dto1:{0}", dto1.Gender);
12     Console.WriteLine("dto2:{0}", dto2.Gender);
c# AutoMapper 使用方式和再封装 随笔 第50张

结果

c# AutoMapper 使用方式和再封装 随笔 第51张

 

八、条件约束Condition

当满足条件时才进行映射字段,例如人类年龄,假设我们现在人类年龄范围为0-200岁(这只是假设),只有满足在这个条件才进行映射

DTO和Entity

c# AutoMapper 使用方式和再封装 随笔 第52张
1     public class User
2     {
3         public int Age { get; set; }
4     }
5 
6     public class UserDto
7     {
8         public int Age { get; set; }
9     }
c# AutoMapper 使用方式和再封装 随笔 第53张

Profile

c# AutoMapper 使用方式和再封装 随笔 第54张
1     public class UserProfile : Profile
2     {
3         protected override void Configure()
4         {
5             CreateMap<User, UserDto>().ForMember(dest=>dest.Age,opt=>opt.Condition(src=>src.Age>=0 && src.Age<=200));
6         }
7     }
c# AutoMapper 使用方式和再封装 随笔 第55张

使用代码

c# AutoMapper 使用方式和再封装 随笔 第56张
 1     Mapper.Initialize(x => x.AddProfile<UserProfile>());
 2 
 3     User user0 = new User() { Age = 1 };
 4     User user1 = new User() { Age = 150 };
 5     User user2 = new User() { Age = 201 };
 6     var dto0= Mapper.Map<UserDto>(user0);
 7     var dto1 = Mapper.Map<UserDto>(user1);
 8     var dto2 = Mapper.Map<UserDto>(user2);
 9 
10     Console.WriteLine("dto0:{0}", dto0.Age);
11     Console.WriteLine("dto1:{0}", dto1.Age);
12     Console.WriteLine("dto2:{0}", dto2.Age);
c# AutoMapper 使用方式和再封装 随笔 第57张

输出结果

c# AutoMapper 使用方式和再封装 随笔 第58张

 

 

出处:https://www.cnblogs.com/caoyc/p/6367828.html

===================================================

AutoMapper介绍

为什么要使用AutoMapper?

我们在实现两个实体之间的转换,首先想到的就是新的一个对象,这个实体的字段等于另一个实体的字段,这样确实能够实现两个实体之间的转换,但这种方式的扩展性,灵活性非常差,维护起来相当麻烦;实体之前转换的工具有很多,不过我还是决定使用AutoMapper,因为它足够轻量级,而且也非常流行,国外的大牛们都使用它使用AutoMapper可以很方便的实现实体和实体之间的转换,它是一个强大的对象映射工具。

一,如何添加AutoMapper到项目中?

在vs中使用打开工具 - 库程序包管理器 - 程序包管理控制平台,输入“Install-Package AutoMapper”命令,就可以把AutoMapper添加到项目中了〜

二,举个栗子

栗子1:两个实体之间的映射

Mapper.CreateMap <Test1,Test2>(); Test1 test1 = new Test1 {Id = 1,Name =“张三”,Date = DateTime.Now}; Test2 test2 = Mapper.Map <Test2>(test1);
 

栗子2:两个实体不同字段之间的映射

 

Mapper.CreateMap <Test1,Test2>()。ForMember(d => d.Name121,opt => opt.MapFrom(s => s.Name));
 

栗子3:泛型之间的映射

  1.     Mapper.CreateMap <Test1,Test2>(); 
  2.               var testList = Mapper.Map <List <Test1>,List <Test2 >>(testList);

三,扩展映射方法使映射变得更简单

 

  1.   using System.Collections;
  2.   using System.Collections.Generic;
  3.   using System.Data;
  4.   using AutoMapper;
  5.   namespace Infrastructure.Utility
  6.    
  7.   {
  8.   /// <summary>
  9.   /// AutoMapper扩展帮助类
  10.   /// </summary>
  11.   public static class AutoMapperHelper
  12.   {
  13.   /// <summary>
  14.   /// 类型映射
  15.   /// </summary>
  16.   public static T MapTo<T>( this object obj)
  17.   {
  18.   if (obj == null) return default(T);
  19.   Mapper.CreateMap(obj.GetType(), typeof(T));
  20.   return Mapper.Map<T>(obj);
  21.   }
  22.   /// <summary>
  23.   /// 集合列表类型映射
  24.   /// </summary>
  25.   public static List<TDestination> MapToList<TDestination>( this IEnumerable source)
  26.   {
  27.   foreach ( var first in source)
  28.   {
  29.   var type = first.GetType();
  30.   Mapper.CreateMap(type, typeof(TDestination));
  31.   break;
  32.   }
  33.   return Mapper.Map<List<TDestination>>(source);
  34.   }
  35.   /// <summary>
  36.   /// 集合列表类型映射
  37.   /// </summary>
  38.   public static List<TDestination> MapToList<TSource, TDestination>( this IEnumerable<TSource> source)
  39.   {
  40.   //IEnumerable<T> 类型需要创建元素的映射
  41.   Mapper.CreateMap<TSource, TDestination>();
  42.   return Mapper.Map<List<TDestination>>(source);
  43.   }
  44.   /// <summary>
  45.   /// 类型映射
  46.   /// </summary>
  47.   public static TDestination MapTo<TSource, TDestination>( this TSource source, TDestination destination)
  48.   where TSource : class
  49.   where TDestination : class
  50.   {
  51.   if (source == null) return destination;
  52.   Mapper.CreateMap<TSource, TDestination>();
  53.   return Mapper.Map(source, destination);
  54.   }
  55.   /// <summary>
  56.   /// DataReader映射
  57.   /// </summary>
  58.   public static IEnumerable<T> DataReaderMapTo<T>( this IDataReader reader)
  59.   {
  60.   Mapper.Reset();
  61.   Mapper.CreateMap<IDataReader, IEnumerable<T>>();
  62.   return Mapper.Map<IDataReader, IEnumerable<T>>(reader);
  63.   }
  64.   }
  65.   }

这样的话,你就可以这样使用了

    var testDto = test.MapTo <Test2>(); 

    var testDtoList = testList.MapTo <Test2>();

 

 

 

出处:https://blog.csdn.net/qq_35193189/article/details/80805451

=========================================================

根据上面的理解和站在巨人的肩膀上,自己重新封装一次,用到项目中。

c# AutoMapper 使用方式和再封装 随笔 第59张
    public static class AutoMapHelper
    {

        /// <summary>
        ///  类型映射,默认字段名字一一对应
        /// </summary>
        /// <typeparam name="TDestination"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static TDestination AutoMapTo<TDestination>(this object obj)
        {
            if (obj == null) return default(TDestination);
            var config = new AutoMapper.MapperConfiguration(cfg => cfg.CreateMap(obj.GetType(), typeof(TDestination)));
            return config.CreateMapper().Map<TDestination>(obj);
        }

        /// <summary>
        /// 类型映射,可指定映射字段的配置信息
        /// </summary>
        /// <typeparam name="TSource">源数据:要被转化的实体对象</typeparam>
        /// <typeparam name="TDestination">目标数据:转换后的实体对象</typeparam>
        /// <param name="source">任何引用类型对象</param>
        /// <param name="cfgExp">可为null,则自动一一映射</param>
        /// <returns></returns>
        public static TDestination AutoMapTo<TSource, TDestination>(this TSource source, Action<AutoMapper.IMapperConfigurationExpression> cfgExp)
         where TDestination : class
         where TSource : class
        {
            if (source == null) return default(TDestination);
            var config = new AutoMapper.MapperConfiguration(cfgExp != null ? cfgExp : cfg => cfg.CreateMap<TSource, TDestination>());
            var mapper = config.CreateMapper();
            return mapper.Map<TDestination>(source);
        }



        /// <summary>
        /// 类型映射,默认字段名字一一对应
        /// </summary>
        /// <typeparam name="TSource">源数据:要被转化的实体对象</typeparam>
        /// <typeparam name="TDestination">目标数据:转换后的实体对象</typeparam>
        /// <param name="source">任何引用类型对象</param>
        /// <returns>转化之后的实体</returns>
        public static TDestination AutoMapTo<TSource, TDestination>(this TSource source)
            where TDestination : class
            where TSource : class
        {
            if (source == null) return default(TDestination);
            var config = new AutoMapper.MapperConfiguration(cfg => cfg.CreateMap<TSource, TDestination>());
            var mapper = config.CreateMapper();
            return mapper.Map<TDestination>(source);
        }


        /// <summary>
        /// 集合列表类型映射,默认字段名字一一对应
        /// </summary>
        /// <typeparam name="TDestination">转化之后的实体对象,可以理解为viewmodel</typeparam>
        /// <typeparam name="TSource">要被转化的实体对象,Entity</typeparam>
        /// <param name="source">通过泛型指定的这个扩展方法的类型,理论任何引用类型</param>
        /// <returns>转化之后的实体列表</returns>
        public static IEnumerable<TDestination> AutoMapTo<TSource, TDestination>(this IEnumerable<TSource> source)
            where TDestination : class
            where TSource : class
        {
            if (source == null) return new List<TDestination>();
            var config = new AutoMapper.MapperConfiguration(cfg => cfg.CreateMap<TSource, TDestination>());
            var mapper = config.CreateMapper();
            return mapper.Map<List<TDestination>>(source);
        }



    }
View Code

 其实还可以继续优化,在泛型中不需要知道指定source的类型了,因为可以直接获取到,后面有时间再调整吧。

,

安装方式:使用vs自带的nuget管理工具,搜索AutoMapper ,选择第一个安装到你的项目即可。

我从网上找了一些资料,

参考网址:http://blog.csdn.net/csethcrm/article/details/52934325

下载了个demo,然后自己又写了一遍,我把AutoMapper 的使用分为两种:

1、viewmodel与实体的字段名字是一致的,viewmodel的字段可以与实体中的字段数量不一致。 

还有一种情况是:源实体中的字段名字是Getxxx,那么viewmodel中对应的字段可以是xxx,也会自动对应赋值,比如我写的demo中源实体中GetA,viewmodel中的A;

再有一种情况就是实体中的实体赋值,在我写的这个例子中,源实体中包含的实体类字段为Sub,里面包含的字段名字为Age,

那么destmodel中对应的字段名字可以是:SubAge,那么automapper就可以自动为你赋值了,大家看最后的运行结果。

给大家看下我建的源实体:

c# AutoMapper 使用方式和再封装 随笔 第61张
    public class Source1 { public string Name { set; get; } public string GetA { set; get; }
public string GetD { set; get; } public string SetB { set; get; } public string c { set; get; } public SubSource1 Sub { set; get; } } public class SubSource1 { public string Age { set; get; } }
c# AutoMapper 使用方式和再封装 随笔 第62张

还有viewmodel(要转化成为你想要的模型):

c# AutoMapper 使用方式和再封装 随笔 第63张
    public class Dest1 { public string Name { set; get; } public string A { set; get; } public string C { set; get; } public string SubAge { set; get; } public string D { set; get; } }
c# AutoMapper 使用方式和再封装 随笔 第64张

我封装的扩展方法:

 

c# AutoMapper 使用方式和再封装 随笔 第65张
        /// <summary>
        /// 类型映射,默认字段名字一一对应 /// </summary>
        /// <typeparam name="TDestination">转化之后的model,可以理解为viewmodel</typeparam>
        /// <typeparam name="TSource">要被转化的实体,Entity</typeparam>
        /// <param name="source">可以使用这个扩展方法的类型,任何引用类型</param>
        /// <returns>转化之后的实体</returns>
        public static TDestination MapTo<TDestination, TSource>(this TSource source) where TDestination : class
            where TSource : class { if (source == null) return default(TDestination); var config = new MapperConfiguration(cfg => cfg.CreateMap<TSource, TDestination>()); var mapper = config.CreateMapper(); return mapper.Map<TDestination>(source); }
c# AutoMapper 使用方式和再封装 随笔 第66张

  

使用方式:

c# AutoMapper 使用方式和再封装 随笔 第67张
                var source1 = new Source1 { Name = "source", Sub = new SubSource1 { Age = "25" }, c = "c", GetA = "A", SetB = "B" }; var destViewModel = source1.MapTo<Source1,Dest1>();
c# AutoMapper 使用方式和再封装 随笔 第68张

运行结果:

c# AutoMapper 使用方式和再封装 随笔 第69张

 

 

2.viewmodel与实体字段名字没有全部对应,只有几个字段的名字和源实体中的字段名字是一样的,其他的字段是通过实体中的几个字段组合或者是格式或者是类型转化而来的,

使用方法:不能再使用这个扩展方法了,只能自己额外写代码,代码如下:

c# AutoMapper 使用方式和再封装 随笔 第70张
               var config2 = new MapperConfiguration( cfg => cfg.CreateMap<SourceUser, DestUser2>() .ForMember(d => d.DestName, opt => opt.MapFrom(s => s.Name))    //指定字段一一对应
                        .ForMember(d => d.Birthday, opt => opt.MapFrom(src => src.Birthday.ToString("yy-MM-dd HH:mm")))//指定字段,并转化指定的格式
                        .ForMember(d => d.Age, opt => opt.Condition(src => src.Age > 5))//条件赋值
                        .ForMember(d => d.A1, opt => opt.Ignore())//忽略该字段,不给该字段赋值
                        .ForMember(d => d.A1, opt => opt.NullSubstitute("Default Value"))//如果源字段值为空,则赋值为 Default Value
                        .ForMember(d => d.A1, opt => opt.MapFrom(src => src.Name + src.Age * 3 + src.Birthday.ToString("d"))));//可以自己随意组合赋值
                var mapper2 = config2.CreateMapper();
c# AutoMapper 使用方式和再封装 随笔 第71张

注释中都包含了平时常用的几种情况,其他的我就没有再写。

下面再给大家把list转化的扩展方法代码贴上:

 

c# AutoMapper 使用方式和再封装 随笔 第72张
        /// <summary>
        /// 集合列表类型映射,默认字段名字一一对应 /// </summary>
        /// <typeparam name="TDestination">转化之后的model,可以理解为viewmodel</typeparam>
        /// <typeparam name="TSource">要被转化的实体,Entity</typeparam>
        /// <param name="source">可以使用这个扩展方法的类型,任何引用类型</param>
        /// <returns>转化之后的实体列表</returns>
        public static IEnumerable<TDestination> MapToList<TSource,TDestination>(this IEnumerable<TSource> source) where TDestination : class
            where TSource : class { if (source == null) return new List<TDestination>(); var config = new MapperConfiguration(cfg => cfg.CreateMap<TSource, TDestination>()); var mapper = config.CreateMapper(); return mapper.Map<List<TDestination>>(source); }
c# AutoMapper 使用方式和再封装 随笔 第73张

  

同样的使用方式:

c# AutoMapper 使用方式和再封装 随笔 第74张
                var source1 = new Source1 { Name = "source", Sub = new SubSource1 { Age = "25" }, c = "c", GetA = "A", SetB = "B" };           var source3 = new Source1 { Name = "source3", Sub = new SubSource1 { Age = "253" }, c = "c3", GetA = "A3", SetB = "B3" }; var sourceList = new List<Source1> { source1, source3 }; var destViewModelList = sourceList.MapToList<Source1,Dest1>();
c# AutoMapper 使用方式和再封装 随笔 第75张

运行结果:

c# AutoMapper 使用方式和再封装 随笔 第76张

 

 

以上就是我个人所得,如有错误,欢迎大家指正。

 

//2017.12.4 修改:destination和source写反了,导致我的总结有些错误,现在纠正一下:错误结论已经红色标注,中间的截图也换成正确的了,工具类方法也已经修正。

,

一、最简单的用法

有两个类User和UserDto

c# AutoMapper 使用方式和再封装 随笔 第77张
 1     public class User
 2     {
 3         public int Id { get; set; }
 4         public string Name { get; set; }
 5         public int Age { get; set; }
 6     }
 7 
 8     public class UserDto
 9     {
10         public string Name { get; set; }
11         public int Age { get; set; }
12     }
c# AutoMapper 使用方式和再封装 随笔 第78张

将User转换成UserDto也和简单

c# AutoMapper 使用方式和再封装 随笔 第79张
1     Mapper.Initialize(x => x.CreateMap<User, UserDto>());
2     User user = new User()
3     {
4         Id = 1,
5         Name = "caoyc",
6         Age = 20
7     };
8     var dto = Mapper.Map<UserDto>(user);
c# AutoMapper 使用方式和再封装 随笔 第80张

 这是一种最简单的使用,AutoMapper会更加字段名称去自动对于,忽略大小写。

 

二、如果属性名称不同

将UserDto的Name属性改成Name2

c# AutoMapper 使用方式和再封装 随笔 第81张
 1     Mapper.Initialize(x => 
 2         x.CreateMap<User, UserDto>()
 3          .ForMember(d =>d.Name2, opt => {
 4             opt.MapFrom(s => s.Name);
 5             })
 6         );
 7 
 8     User user = new User()
 9     {
10         Id = 1,
11         Name = "caoyc",
12         Age = 20
13     };
14 
15     var dto = Mapper.Map<UserDto>(user);
c# AutoMapper 使用方式和再封装 随笔 第82张

c# AutoMapper 使用方式和再封装 随笔 第83张

 

三、使用Profile配置

自定义一个UserProfile类继承Profile,并重写Configure方法

c# AutoMapper 使用方式和再封装 随笔 第84张
 1     public class UserProfile : Profile
 2     {
 3         protected override void Configure()
 4         {
 5             CreateMap<User, UserDto>()
 6                 .ForMember(d => d.Name2, opt =>
 7                 {
 8                     opt.MapFrom(s => s.Name);
 9                 });
10         }
11     }
c# AutoMapper 使用方式和再封装 随笔 第85张

使用时就这样

c# AutoMapper 使用方式和再封装 随笔 第86张
 1     Mapper.Initialize(x => x.AddProfile<UserProfile>());
 2 
 3     User user = new User()
 4     {
 5         Id = 1,
 6         Name = "caoyc",
 7         Age = 20
 8     };
 9 
10     var dto = Mapper.Map<UserDto>(user);
c# AutoMapper 使用方式和再封装 随笔 第87张

 

四、空值替换NullSubstitute

空值替换允许我们将Source对象中的空值在转换为Destination的值的时候,使用指定的值来替换空值。

c# AutoMapper 使用方式和再封装 随笔 第88张
 1     public class UserProfile : Profile
 2     {
 3         protected override void Configure()
 4         {
 5             CreateMap<User, UserDto>()
 6                 .ForMember(d => d.Name2, opt => opt.MapFrom(s => s.Name))
 7                 .ForMember(d => d.Name2, opt => opt.NullSubstitute("值为空"));
 8                 
 9         }
10     }
c# AutoMapper 使用方式和再封装 随笔 第89张 c# AutoMapper 使用方式和再封装 随笔 第90张
1     Mapper.Initialize(x => x.AddProfile<UserProfile>());
2 
3     User user = new User()
4     {
5         Id = 1,
6         Age = 20
7     };
8 
9     var dto = Mapper.Map<UserDto>(user);
c# AutoMapper 使用方式和再封装 随笔 第91张

结果为:

c# AutoMapper 使用方式和再封装 随笔 第92张

 

五、忽略属性Ignore

c# AutoMapper 使用方式和再封装 随笔 第93张
 1     public class User
 2     {
 3         public int Id { get; set; }
 4         public string Name { get; set; }
 5         public int Age { get; set; }
 6     }
 7 
 8     public class UserDto
 9     {
10         public string Name { get; set; }
11         public int Age { get; set; }
12 
13     }
14 
15     public class UserProfile : Profile
16     {
17         protected override void Configure()
18         {
19             CreateMap<User, UserDto>().ForMember("Name", opt => opt.Ignore());
20         }
21     }
c# AutoMapper 使用方式和再封装 随笔 第94张

使用

c# AutoMapper 使用方式和再封装 随笔 第95张
 1     Mapper.Initialize(x => x.AddProfile<UserProfile>());
 2 
 3     User user = new User()
 4     {
 5         Id = 1,
 6         Name="caoyc",
 7         Age = 20
 8     };
 9 
10     var dto = Mapper.Map<UserDto>(user);
c# AutoMapper 使用方式和再封装 随笔 第96张

结果:

c# AutoMapper 使用方式和再封装 随笔 第97张

 

六、预设值

如果目标属性多于源属性,可以进行预设值

c# AutoMapper 使用方式和再封装 随笔 第98张
 1     public class User
 2     {
 3         public int Id { get; set; }
 4         public string Name { get; set; }
 5         public int Age { get; set; }
 6     }
 7 
 8     public class UserDto
 9     {
10         public string Name { get; set; }
11         public int Age { get; set; }
12         public string Gender { get; set; }
13 
14     }
15 
16     public class UserProfile : Profile
17     {
18         protected override void Configure()
19         {
20             CreateMap<User, UserDto>();
21         }
22     }
c# AutoMapper 使用方式和再封装 随笔 第99张

使用

c# AutoMapper 使用方式和再封装 随笔 第100张
 1     Mapper.Initialize(x => x.AddProfile<UserProfile>());
 2 
 3     User user = new User()
 4     {
 5         Id = 1,
 6         Name="caoyc",
 7         Age = 20
 8     };
 9 
10     UserDto dto = new UserDto() {Gender = ""};
11     Mapper.Map(user, dto);
c# AutoMapper 使用方式和再封装 随笔 第101张

c# AutoMapper 使用方式和再封装 随笔 第102张

 七、类型转换ITypeConverter

如果数据中Gender存储的int类型,而DTO中Gender是String类型

c# AutoMapper 使用方式和再封装 随笔 第103张
1     public class User
2     {
3         public int Gender { get; set; }
4     }
5 
6     public class UserDto
7     {
8         public string Gender { get; set; }
9     }
c# AutoMapper 使用方式和再封装 随笔 第104张

类型转换类,需要实现接口ITypeConverter

c# AutoMapper 使用方式和再封装 随笔 第105张
 1     public class GenderTypeConvertert : ITypeConverter<int, string>
 2     {
 3         public string Convert(int source, string destination, ResolutionContext context)
 4         {
 5             switch (source)
 6             {
 7                 case 0:
 8                     destination = "";
 9                     break;
10                 case 1:
11                     destination = "";
12                     break;
13                 default:
14                     destination = "未知";
15                     break;
16             }
17             return destination;
18         }
19     }
c# AutoMapper 使用方式和再封装 随笔 第106张

配置规则

c# AutoMapper 使用方式和再封装 随笔 第107张
 1     public class UserProfile : Profile
 2     {
 3         protected override void Configure()
 4         {
 5             CreateMap<User, UserDto>();
 6 
 7             CreateMap<int, string>().ConvertUsing<GenderTypeConvertert>();
 8             //也可以写这样
 9             //CreateMap<int, string>().ConvertUsing(new GenderTypeConvertert());
10         }
11     }
c# AutoMapper 使用方式和再封装 随笔 第108张

使用

c# AutoMapper 使用方式和再封装 随笔 第109张
 1     Mapper.Initialize(x => x.AddProfile<UserProfile>());
 2 
 3     User user0 = new User() { Gender = 0 };
 4     User user1 = new User() { Gender = 1 };
 5     User user2 = new User() { Gender = 2 };
 6     var dto0= Mapper.Map<UserDto>(user0);
 7     var dto1 = Mapper.Map<UserDto>(user1);
 8     var dto2 = Mapper.Map<UserDto>(user2);
 9 
10     Console.WriteLine("dto0:{0}", dto0.Gender);
11     Console.WriteLine("dto1:{0}", dto1.Gender);
12     Console.WriteLine("dto2:{0}", dto2.Gender);
c# AutoMapper 使用方式和再封装 随笔 第110张

结果

c# AutoMapper 使用方式和再封装 随笔 第111张

 

八、条件约束Condition

当满足条件时才进行映射字段,例如人类年龄,假设我们现在人类年龄范围为0-200岁(这只是假设),只有满足在这个条件才进行映射

DTO和Entity

c# AutoMapper 使用方式和再封装 随笔 第112张
1     public class User
2     {
3         public int Age { get; set; }
4     }
5 
6     public class UserDto
7     {
8         public int Age { get; set; }
9     }
c# AutoMapper 使用方式和再封装 随笔 第113张

Profile

c# AutoMapper 使用方式和再封装 随笔 第114张
1     public class UserProfile : Profile
2     {
3         protected override void Configure()
4         {
5             CreateMap<User, UserDto>().ForMember(dest=>dest.Age,opt=>opt.Condition(src=>src.Age>=0 && src.Age<=200));
6         }
7     }
c# AutoMapper 使用方式和再封装 随笔 第115张

使用代码

c# AutoMapper 使用方式和再封装 随笔 第116张
 1     Mapper.Initialize(x => x.AddProfile<UserProfile>());
 2 
 3     User user0 = new User() { Age = 1 };
 4     User user1 = new User() { Age = 150 };
 5     User user2 = new User() { Age = 201 };
 6     var dto0= Mapper.Map<UserDto>(user0);
 7     var dto1 = Mapper.Map<UserDto>(user1);
 8     var dto2 = Mapper.Map<UserDto>(user2);
 9 
10     Console.WriteLine("dto0:{0}", dto0.Age);
11     Console.WriteLine("dto1:{0}", dto1.Age);
12     Console.WriteLine("dto2:{0}", dto2.Age);
c# AutoMapper 使用方式和再封装 随笔 第117张

输出结果

c# AutoMapper 使用方式和再封装 随笔 第118张

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄