前言
上一篇介紹了三層式架構,有些人可能會有疑問,三層各有自己的 Model ,那要怎麼將各個 Model 轉換呢?
難道是每一次轉換都需要跑一次迴圈,那也太麻煩了;這時就要介紹好用的工具 Automapper了。
本文
基本用法
首先到 Nuget 安裝 Automapper。
安裝好後我們建立兩個測試用的 Model
private class Model1
{
public string Name { get; set; }
public int Id { get; set; }
}
private class Model2
{
public string Name { get; set; }
public int Id { get; set; }
}
使用 Automapper 對應 Model1 到 Model2。
var testModel = new Model1
{
Name = "ALLEN",
Id = 1
};
var config = new MapperConfiguration(cfg => cfg.CreateMap<Model1, Model2>());
//從左邊Model對應到右邊
var mapper = config.CreateMapper();
var model2 = mapper.Map<Model2>(testModel);
Console.WriteLine($"Model2 Id:{model2.Id}");
Console.WriteLine($"Model2 Name:{model2.Name}");
結果:
如此一來就可以很輕鬆的對應 Model 了。
偷懶小技巧:如果一時分不清是哪個 Model 要對應到哪個 Model,那可以加上 ReverseMap 反轉雙向對應。
var config = new MapperConfiguration(cfg =>
cfg.CreateMap<Model1, Model2>().ReverseMap());
客製化對應
我們上一篇講到的三層式架構,有提到每一層分工的時候會建立自己的 Model 有的時候可能各層間 Model 命名方式不同、或是需要對 Model 進行特殊處理,那就可以用以下方法來處理對應。
一樣先建立兩個測試用 Model
private class Model1
{
public string Name { get; set; }
public int Id { get; set; }
}
private class Model2
{
public string Name { get; set; }
public int UserId { get; set; }
}
建立對應:
var testModel = new Model1
{
Name = "ALLEN",
Id = 1
};
var config = new MapperConfiguration(cfg =>
cfg.CreateMap<Model1, Model2>()
.ForMember(x => x.UserId, y => y.MapFrom(z => z.Id)));
var mapper = config.CreateMapper();
var model2 = mapper.Map<Model2>(testModel);
Console.WriteLine($"Model2 Id:{model2.UserId}");
Console.WriteLine($"Model2 Name:{model2.Name}");
結果:
進行特殊處理方式
首先在 Model2 多加一個 string
private class Model2
{
public string Name { get; set; }
public int UserId { get; set; }
public string User { get; set; }
}
var testModel = new Model1
{
Name = "ALLEN",
Id = 1
};
var config = new MapperConfiguration(cfg =>
cfg.CreateMap<Model1, Model2>()
.ForMember(x => x.UserId, y => y.MapFrom(z => z.Id))
.ForMember(x => x.User, y => y.MapFrom(z => $"{z.Id}、{z.Name}")));
var mapper = config.CreateMapper();
var model2 = mapper.Map<Model2>(testModel);
Console.WriteLine($"Model2 UserId:{model2.UserId}");
Console.WriteLine($"Model2 Name:{model2.Name}");
Console.WriteLine($"Model2 User:{model2.User}");
結果:
這邊做點小提醒,因為可以透過此種方式很方便的對 Model 對應出來的資料動手腳,那麼下一個人接手的時候就有機會找不到資料是在哪邊被動過了,所以使用 ForMember 做特殊對應的話建議還是要特別註明。
忽略對應
除了可以做到小處理 Automapper 也支援忽略對應,可以用此種方式達到。
private static void Main(string[] args)
{
var testModel = new Model1
{
Name = "ALLEN",
Id = 1
};
var config = new MapperConfiguration(cfg =>
cfg.CreateMap<Model1, Model2>()
.ForMember(x => x.UserId, y => y.Ignore()) //忽略此項
.ForMember(x => x.User, y => y.MapFrom(z => $"{z.Id}、{z.Name}")));
var mapper = config.CreateMapper();
var model2 = mapper.Map<Model2>(testModel);
Console.WriteLine($"Model2 UserId:{model2.UserId}");
Console.WriteLine($"Model2 Name:{model2.Name}");
Console.WriteLine($"Model2 User:{model2.User}");
}
結果:
集中管理
上面示範用法都是在個別區塊中使用,這樣不方便管理,我們可以建立一個 profile 檔案繼承 Automapper 的 profile 來集中管理這些 mapping。
首先 dotnet core 要先安裝 AutoMapper.Extensions.Microsoft.DependencyInjection。
接下來建立一個 profile 檔案繼承 Profile。
public class ControllerProfile : Profile
{
public ControllerProfile()
{
CreateMap<Model1, Model2>();
//CreateMap<>(); 接著建立其他mapping
}
}
再到 startup 內 ConfigureServices 註冊 Automapper。
services.AddAutoMapper(typeof(ControllerProfile));
//將剛剛建好的ControllerProfile加入註冊
接下來我們可以透過注入的方式使用 mapping。
private IMapper _mapper;
public WeatherForecastController(
IMapper mapper)
{
this._mapper = mapper;
}
測試一下
public Model2 Get()
{
var testModel = new Model1
{
Name = "ALLEN",
Id = 1
};
var model2 = this._mapper.Map<Model2>(testModel);
return model2;
}
如此一來就可以透過簡單的方式轉換各個 Model,提供這方便的套件供大家參考使用。