安裝方式:使用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>();
運行結果:
![](http://static.javashuo.com/static/loading.gif)
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>();
運行結果:
![](http://static.javashuo.com/static/loading.gif)
以上就是我我的所得,若有錯誤,歡迎你們指正。
//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);
![](http://static.javashuo.com/static/loading.gif)
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);
結果爲:
![](http://static.javashuo.com/static/loading.gif)
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);
結果:
![](http://static.javashuo.com/static/loading.gif)
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);
![](http://static.javashuo.com/static/loading.gif)
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);
結果
![](http://static.javashuo.com/static/loading.gif)
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);
輸出結果
![](http://static.javashuo.com/static/loading.gif)
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