前言

上一篇介紹了三層式架構,有些人可能會有疑問,三層各有自己的 Model ,那要怎麼將各個 Model 轉換呢?

難道是每一次轉換都需要跑一次迴圈,那也太麻煩了;這時就要介紹好用的工具 Automapper了。

本文

基本用法

首先到 Nuget 安裝 Automapper。

安裝好後我們建立兩個測試用的 Model

  1. private class Model1
  2. {
  3. public string Name { get; set; }
  4. public int Id { get; set; }
  5. }
  6. private class Model2
  7. {
  8. public string Name { get; set; }
  9. public int Id { get; set; }
  10. }

使用 Automapper 對應 Model1 到 Model2。

  1. var testModel = new Model1
  2. {
  3. Name = "ALLEN",
  4. Id = 1
  5. };
  6. var config = new MapperConfiguration(cfg => cfg.CreateMap<Model1, Model2>());
  7. //從左邊Model對應到右邊
  8. var mapper = config.CreateMapper();
  9. var model2 = mapper.Map<Model2>(testModel);
  10. Console.WriteLine($"Model2 Id:{model2.Id}");
  11. Console.WriteLine($"Model2 Name:{model2.Name}");

結果:

如此一來就可以很輕鬆的對應 Model 了。

偷懶小技巧:如果一時分不清是哪個 Model 要對應到哪個 Model,那可以加上 ReverseMap 反轉雙向對應。

  1. var config = new MapperConfiguration(cfg =>
  2. cfg.CreateMap<Model1, Model2>().ReverseMap());

客製化對應

我們上一篇講到的三層式架構,有提到每一層分工的時候會建立自己的 Model 有的時候可能各層間 Model 命名方式不同、或是需要對 Model 進行特殊處理,那就可以用以下方法來處理對應。

一樣先建立兩個測試用 Model

  1. private class Model1
  2. {
  3. public string Name { get; set; }
  4. public int Id { get; set; }
  5. }
  6. private class Model2
  7. {
  8. public string Name { get; set; }
  9. public int UserId { get; set; }
  10. }

建立對應:

  1. var testModel = new Model1
  2. {
  3. Name = "ALLEN",
  4. Id = 1
  5. };
  6. var config = new MapperConfiguration(cfg =>
  7. cfg.CreateMap<Model1, Model2>()
  8. .ForMember(x => x.UserId, y => y.MapFrom(z => z.Id)));
  9. var mapper = config.CreateMapper();
  10. var model2 = mapper.Map<Model2>(testModel);
  11. Console.WriteLine($"Model2 Id:{model2.UserId}");
  12. Console.WriteLine($"Model2 Name:{model2.Name}");

結果:

進行特殊處理方式

首先在 Model2 多加一個 string

  1. private class Model2
  2. {
  3. public string Name { get; set; }
  4. public int UserId { get; set; }
  5. public string User { get; set; }
  6. }
  1. var testModel = new Model1
  2. {
  3. Name = "ALLEN",
  4. Id = 1
  5. };
  6. var config = new MapperConfiguration(cfg =>
  7. cfg.CreateMap<Model1, Model2>()
  8. .ForMember(x => x.UserId, y => y.MapFrom(z => z.Id))
  9. .ForMember(x => x.User, y => y.MapFrom(z => $"{z.Id}、{z.Name}")));
  10. var mapper = config.CreateMapper();
  11. var model2 = mapper.Map<Model2>(testModel);
  12. Console.WriteLine($"Model2 UserId:{model2.UserId}");
  13. Console.WriteLine($"Model2 Name:{model2.Name}");
  14. Console.WriteLine($"Model2 User:{model2.User}");

結果:

這邊做點小提醒,因為可以透過此種方式很方便的對 Model 對應出來的資料動手腳,那麼下一個人接手的時候就有機會找不到資料是在哪邊被動過了,所以使用 ForMember 做特殊對應的話建議還是要特別註明。

忽略對應

除了可以做到小處理 Automapper 也支援忽略對應,可以用此種方式達到。

  1. private static void Main(string[] args)
  2. {
  3. var testModel = new Model1
  4. {
  5. Name = "ALLEN",
  6. Id = 1
  7. };
  8. var config = new MapperConfiguration(cfg =>
  9. cfg.CreateMap<Model1, Model2>()
  10. .ForMember(x => x.UserId, y => y.Ignore()) //忽略此項
  11. .ForMember(x => x.User, y => y.MapFrom(z => $"{z.Id}、{z.Name}")));
  12. var mapper = config.CreateMapper();
  13. var model2 = mapper.Map<Model2>(testModel);
  14. Console.WriteLine($"Model2 UserId:{model2.UserId}");
  15. Console.WriteLine($"Model2 Name:{model2.Name}");
  16. Console.WriteLine($"Model2 User:{model2.User}");
  17. }

結果:

集中管理

上面示範用法都是在個別區塊中使用,這樣不方便管理,我們可以建立一個 profile 檔案繼承 Automapper 的 profile 來集中管理這些 mapping。

首先 dotnet core 要先安裝 AutoMapper.Extensions.Microsoft.DependencyInjection。

接下來建立一個 profile 檔案繼承 Profile。

  1. public class ControllerProfile : Profile
  2. {
  3. public ControllerProfile()
  4. {
  5. CreateMap<Model1, Model2>();
  6. //CreateMap<>(); 接著建立其他mapping
  7. }
  8. }

再到 startup 內 ConfigureServices 註冊 Automapper。

  1. services.AddAutoMapper(typeof(ControllerProfile));
  2. //將剛剛建好的ControllerProfile加入註冊

接下來我們可以透過注入的方式使用 mapping。

  1. private IMapper _mapper;
  2. public WeatherForecastController(
  3. IMapper mapper)
  4. {
  5. this._mapper = mapper;
  6. }

測試一下

  1. public Model2 Get()
  2. {
  3. var testModel = new Model1
  4. {
  5. Name = "ALLEN",
  6. Id = 1
  7. };
  8. var model2 = this._mapper.Map<Model2>(testModel);
  9. return model2;
  10. }

如此一來就可以透過簡單的方式轉換各個 Model,提供這方便的套件供大家參考使用。

參考連結