安装方式:使用vs自带的nuget管理工具,搜索AutoMapper ,选择第一个安装到你的项目便可。php
我从网上找了一些资料,html
参考网址:http://blog.csdn.net/csethcrm/article/details/52934325app
下载了个demo,而后本身又写了一遍,我把AutoMapper 的使用分为两种:ide
一、viewmodel与实体的字段名字是一致的,viewmodel的字段能够与实体中的字段数量不一致。 函数
还有一种状况是:源实体中的字段名字是Getxxx,那么viewmodel中对应的字段能够是xxx,也会自动对应赋值,好比我写的demo中源实体中GetA,viewmodel中的A;工具
再有一种状况就是实体中的实体赋值,在我写的这个例子中,源实体中包含的实体类字段为Sub,里面包含的字段名字为Age,post
那么destmodel中对应的字段名字能够是:SubAge,那么automapper就能够自动为你赋值了,你们看最后的运行结果。优化
给你们看下我建的源实体:this
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; } }
还有viewmodel(要转化成为你想要的模型):spa
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; } }
我封装的扩展方法:
/// <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); }
使用方式:
var source1 = new Source1 { Name = "source", Sub = new SubSource1 { Age = "25" }, c = "c", GetA = "A", SetB = "B" }; var destViewModel = source1.MapTo<Source1,Dest1>();
运行结果:

2.viewmodel与实体字段名字没有所有对应,只有几个字段的名字和源实体中的字段名字是同样的,其余的字段是经过实体中的几个字段组合或者是格式或者是类型转化而来的,
使用方法:不能再使用这个扩展方法了,只能本身额外写代码,代码以下:
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();
注释中都包含了平时经常使用的几种状况,其余的我就没有再写。
下面再给你们把list转化的扩展方法代码贴上:
/// <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); }
一样的使用方式:
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>();
运行结果:

以上就是我我的所得,若有错误,欢迎你们指正。
//2017.12.4 修改:destination和source写反了,致使个人总结有些错误,如今纠正一下:错误结论已经红色标注,中间的截图也换成正确的了,工具类方法也已经修正。
1、最简单的用法
有两个类User和UserDto
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 }
将User转换成UserDto也和简单
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);
这是一种最简单的使用,AutoMapper会更加字段名称去自动对于,忽略大小写。
2、若是属性名称不一样
将UserDto的Name属性改为Name2
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);

3、使用Profile配置
自定义一个UserProfile类继承Profile,并重写Configure方法
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 }
新版本的 autoMapper.UserProfile.Configure()”: 可能会有提示:没有找到适合的方法来重写 。
能够改成构造函数注入的方式
public class UserProfile : Profile
{
public UserProfile ()
{
CreateMap<User, UserDto>()
.ForMember(d => d.Name2, opt =>
{
opt.MapFrom(s => s.Name);
});
}
}
使用时就这样
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);
4、空值替换NullSubstitute
空值替换容许咱们将Source对象中的空值在转换为Destination的值的时候,使用指定的值来替换空值。
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 }
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);
结果为:

5、忽略属性Ignore
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 }
使用
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);
结果:

6、预设值
若是目标属性多于源属性,能够进行预设值
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 }
使用
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);

7、类型转换ITypeConverter
若是数据中Gender存储的int类型,而DTO中Gender是String类型
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 }
类型转换类,须要实现接口ITypeConverter
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 }
配置规则
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 }
使用
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);
结果

8、条件约束Condition
当知足条件时才进行映射字段,例如人类年龄,假设咱们如今人类年龄范围为0-200岁(这只是假设),只有知足在这个条件才进行映射
DTO和Entity
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 }
Profile
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 }
使用代码
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);
输出结果

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:泛型之间的映射
-
Mapper.CreateMap <Test1,Test2>();
-
var testList = Mapper.Map <List <Test1>,List <Test2 >>(testList);
三,扩展映射方法使映射变得更简单
-
using System.Collections;
-
using System.Collections.Generic;
-
-
-
namespace
Infrastructure.Utility
-
-
-
-
-
-
public
static
class
AutoMapperHelper
-
-
-
-
-
public
static T MapTo<T>(
this
object obj)
-
-
if (obj ==
null)
return
default(T);
-
Mapper.CreateMap(obj.GetType(),
typeof(T));
-
return Mapper.Map<T>(obj);
-
-
-
-
-
public
static List<TDestination> MapToList<TDestination>(
this IEnumerable source)
-
-
foreach (
var first
in source)
-
-
var type = first.GetType();
-
Mapper.CreateMap(type,
typeof(TDestination));
-
-
-
return Mapper.Map<List<TDestination>>(source);
-
-
-
-
-
public
static List<TDestination> MapToList<TSource, TDestination>(
this IEnumerable<TSource> source)
-
-
-
Mapper.CreateMap<TSource, TDestination>();
-
return Mapper.Map<List<TDestination>>(source);
-
-
-
-
-
public
static TDestination MapTo<TSource, TDestination>(
this TSource source, TDestination destination)
-
-
where
TDestination :
class
-
-
if (source ==
null)
return destination;
-
Mapper.CreateMap<TSource, TDestination>();
-
return Mapper.Map(source, destination);
-
-
-
-
-
public
static IEnumerable<T> DataReaderMapTo<T>(
this IDataReader reader)
-
-
-
Mapper.CreateMap<IDataReader, IEnumerable<T>>();
-
return Mapper.Map<IDataReader, IEnumerable<T>>(reader);
-
-
-
这样的话,你就能够这样使用了
var testDto = test.MapTo <Test2>();
var testDtoList = testList.MapTo <Test2>();
namespace AutoMapperTest
{
class Program
{
static void Main(string[] args)
{
var config = new MapperConfiguration(cif => cif.AddProfile <UserProfile>()); //方式一
//var config = new MapperConfiguration(cif => cif.AddProfile(new UserProfile()));//方式二
var mapper = config.CreateMapper();
var f = new ObjectFrom { TestName = "aaa", TestAge = 12, TestSex = "m" };
Console.WriteLine(JsonConvert.SerializeObject(f) + Environment.NewLine);
var t = mapper.Map<ObjectTo>(f);
Console.WriteLine(JsonConvert.SerializeObject(t) + Environment.NewLine);
Console.ReadKey();
}
}
public class ObjectFrom
{
public string TestName { get; set; }
public int TestAge { get; set; }
public string TestSex { get; set; }
}
public class ObjectTo
{
public ObjectTo(string name)
{
if (name == null)
{
throw new InvalidDataException("name cannot be null");
}
else
{
this._name = name;
}
}
private readonly string _name;
public string Name { get { return _name; } }
public int Age { get; set; }
public string Gender { get; set; }
}
}
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