為了說明AutoMapper如何使用,我專門開設了一個專題來講,如果您還沒有檢視該專題,請點選這裡。既然系統地學習了AutoMapper,那麼接下來就是該用它實戰的時候了。今天,我們就來揭開AutoMapper如何在ABP框架中使用的面紗。
因為這裡演示的是用ABP框架搭建的專案,本部落格的講解的前提是假設你有了ABP基礎,所以,如果您還不瞭解ABP框架,請檢視我的ABP框架的系列部落格,請點選這裡。
下面正式開始今天的講解。
首先,讓我們稍微回憶一下AutoMapper的知識點。
問:什麼是AutoMapper?
答:AutoMapper翻譯過來就是“自動對映工具”。它的作用就是將一個源型別對映成一個目標型別,比如Person——>PersonDto,User——>UserDto。
問:什麼情況下使用AutoMapper?
答:一般在專案的開發中,經常需要將Entity實體對映成ModelDto或者ViewModel,這個時候,使用AutoMapper僅需要簡單的配置,就可以實現這些需求,非常方便。
接下來,講一下專案中的具體配置。
在我的ABP專案中,首先核心層有一個實體類TerminalDevices,類定義如下:
1 namespace Noah.ChargeStation.Core.Entities 2 { 3 //終端表 4 public class TerminalDevices : Entity 5 { 6 7 /// <summary> 8 /// 終端編碼 9 /// </summary> 10 public virtual string Code 11 { 12 get; 13 set; 14 } 15 /// <summary> 16 /// IMEI 17 /// </summary> 18 public virtual string IMEI 19 { 20 get; 21 set; 22 } 23 /// <summary> 24 /// SIMCardNO 25 /// </summary> 26 public virtual string SIMCardNO 27 { 28 get; 29 set; 30 } 31 /// <summary> 32 /// InstallDate 33 /// </summary> 34 public virtual DateTime? InstallDate 35 { 36 get; 37 set; 38 } 39 /// <summary> 40 /// PlacePosition 41 /// </summary> 42 public virtual string PlacePosition 43 { 44 get; 45 set; 46 } 47 /// <summary> 48 /// Version 49 /// </summary> 50 public virtual int? Version 51 { 52 get; 53 set; 54 } 55 /// <summary> 56 /// TotalCoins 57 /// </summary> 58 public virtual int TotalCoins 59 { 60 get; 61 set; 62 } 63 /// <summary> 64 /// CurrentBoxCoins 65 /// </summary> 66 public virtual int CurrentBoxCoins 67 { 68 get; 69 set; 70 } 71 /// <summary> 72 /// 最小計費單位 73 /// </summary> 74 public virtual int MinimumUnit 75 { 76 get; 77 set; 78 } 79 /// <summary> 80 /// 充電時長 81 /// </summary> 82 public virtual int ChargeTime 83 { 84 get; 85 set; 86 } 87 /// <summary> 88 /// MoneyBoxCapacity 89 /// </summary> 90 public virtual int? MoneyBoxCapacity 91 { 92 get; 93 set; 94 } 95 /// <summary> 96 /// 終端名稱 97 /// </summary> 98 public virtual string Name 99 { 100 get; 101 set; 102 } 103 /// <summary> 104 /// 終端型別:0--同城類終端 1--跨城類終端 105 /// </summary> 106 public virtual int? Type 107 { 108 get; 109 set; 110 } 111 /// <summary> 112 /// 所屬城市 113 /// </summary> 114 public virtual int? CityID 115 { 116 get; 117 set; 118 } 119 /// <summary> 120 /// 所屬運營商 121 /// </summary> 122 public virtual int? OperatorID 123 { 124 get; 125 set; 126 } 127 /// <summary> 128 /// 所屬站臺 129 /// </summary> 130 public virtual int? StationID 131 { 132 get; 133 set; 134 } 135 /// <summary> 136 /// 經度 137 /// </summary> 138 public virtual decimal? Longitude 139 { 140 get; 141 set; 142 } 143 /// <summary> 144 /// 緯度 145 /// </summary> 146 public virtual decimal? Latitude 147 { 148 get; 149 set; 150 } 151 /// <summary> 152 /// 支付寶二維碼內容 153 /// </summary> 154 public virtual string AlipayEWMContent 155 { 156 get; 157 set; 158 } 159 /// <summary> 160 /// 支付寶二維碼圖片 161 /// </summary> 162 public virtual string AlipayEWMImage 163 { 164 get; 165 set; 166 } 167 /// <summary> 168 /// 微信二維碼內容 169 /// </summary> 170 public virtual string WechatEWMContent 171 { 172 get; 173 set; 174 } 175 /// <summary> 176 /// 微信二維碼圖片 177 /// </summary> 178 public virtual string WechatEWMImage 179 { 180 get; 181 set; 182 } 183 /// <summary> 184 /// 正在充電數量 185 /// </summary> 186 public virtual int? ChargingNum 187 { 188 get; 189 set; 190 } 191 /// <summary> 192 /// 上次通訊時間 193 /// </summary> 194 public virtual DateTime? LastConnectTime 195 { 196 get; 197 set; 198 } 199 /// <summary> 200 /// 0--失聯 1--正常 2--維修 3--維護4--下線 201 /// </summary> 202 public virtual int? Status 203 { 204 get; 205 set; 206 } 207 /// <summary> 208 /// SystemCode 209 /// </summary> 210 public virtual string SystemCode 211 { 212 get; 213 set; 214 } 215 /// <summary> 216 /// Certificate 217 /// </summary> 218 public virtual string Certificate 219 { 220 get; 221 set; 222 } 223 /// <summary> 224 /// 到期時間 225 /// </summary> 226 public virtual DateTime? DueDate 227 { 228 get; 229 set; 230 } 231 /// <summary> 232 /// 建立人 233 /// </summary> 234 public virtual string CreatedBy 235 { 236 get; 237 set; 238 } 239 /// <summary> 240 /// 建立日期 241 /// </summary> 242 public virtual DateTime? CreatedDate 243 { 244 get; 245 set; 246 } 247 /// <summary> 248 /// 最後更新人 249 /// </summary> 250 public virtual string UpdatedBy 251 { 252 get; 253 set; 254 } 255 /// <summary> 256 /// 最後更新日期 257 /// </summary> 258 public virtual DateTime? UpdatedDate 259 { 260 get; 261 set; 262 } 263 public TerminalDevices() 264 { 265 266 } 267 268 } 269 270 }
可以看到,僅一個實體類,就要將近300行的程式碼,但是在服務層或者展現層使用的時候,有些屬性是不需要的,所以這時我們就要定義我們的Dto類了。
隨後,我在ABP專案中的服務層定義了一個對應的TerminalDeviceDto類,定義如下:
1 namespace Noah.ChargeStation.Application.TerminalDevicesApp.Dto 2 { 3 public class TerminalDeviceDto:IDto 4 { 5 [DisplayName("裝置編碼")] 6 public string Code { get; set; } 7 public string IMEI { get; set; } 8 [DisplayName("SIM卡號")] 9 public string SIMCardNO { get; set; } 10 public string InstallDate { get; set; } 11 public string PlacePosition { get; set; } 12 public int Version { get; set; } 13 [DisplayName("總投幣")] 14 public int TotalCoins { get; set; } 15 public int CurrentBoxCoins { get; set; } 16 public int MinimumUnit { get; set; } 17 public int ChargeTime { get; set; } 18 public int MoneyBoxCapacity { get; set; } 19 public string Name { get; set; } 20 public int Type { get; set; } 21 public int CityId { get; set; } 22 public int OperatorId { get; set; } 23 public int StationId { get; set; } 24 public decimal Longitude { get; set; } 25 public decimal Latitude { get; set; } 26 public string AlipayEWMContent { get; set; } 27 public string AlipayEWMImage { get; set; } 28 public string WechatEWMContent { get; set; } 29 public string WechatEWMImage { get; set; } 30 public int ChargingNum { get; set; } 31 public DateTime LastConnectTime { get; set; } 32 public int Status { get; set; } 33 public string SystemCode { get; set; } 34 public string Certificate { get; set; } 35 public DateTime DueDate { get; set; } 36 public string CreatedBy { get; set; } 37 public DateTime CreatedDate { get; set; } 38 public string UpdatedBy { get; set; } 39 public DateTime UpdatedDate { get; set; } 40 41 } 42 }
當然,這裡的Dto類定義的屬性跟你的具體業務相關,定義的屬性還可能更少。
上面講的是源型別和目標型別的定義,下面開始講它們之間的對映配置。
首先,我在應用服務層新建一個資料夾取名“AutoMapper”,裡面放跟AutoMapper配置相關的東西。
如圖,新建一個類TerminalDeviceProfile(CityProfile類是我的另一個實體類對應的AutoMapper配置檔案),定義如下:
namespace Noah.ChargeStation.Application.AutoMapper { public class CityProfile:Profile { protected override void Configure() { Mapper.Initialize(cfg => { cfg.CreateMap<Cities, CityDto>(); }); } } }
如果您對這麼配置不清楚原因,請檢視我的AutoMapper系列教程,點選檢視。
再建立一個AutoMapperWebConfig靜態類,定義如下:
namespace Noah.ChargeStation.Application.AutoMapper { public static class AutoMapperWebConfig { public static void Configure() { Mapper.Initialize(cfg => { cfg.AddProfile<CityProfile>(); cfg.AddProfile<TerminalDeviceProfile>(); }); Mapper.AssertConfigurationIsValid();//驗證所有的對映配置是否都正常 } } }
接下來,在應用服務層的模組類中呼叫該靜態類的靜態方法,載入所有的AutoMapper配置資訊。
namespace Noah.ChargeStation.Application { [DependsOn(typeof(ChargeStationCoreModule), typeof(AbpAutoMapperModule))] public class ChargeStationApplicationModule : AbpModule { public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); AutoMapperWebConfig.Configure();//一次性載入所有對映配置 } } }
這裡需要注意的是,AutoMapper的配置一般放在專案啟動的時候進行載入且只載入一次就夠了,而在ABP框架搭建的專案中,除了展現層(Web和WebAPI層),其他層都會有一個Module類(類名以Module結尾)。這些類都重寫了父類AbpModule的Initialize方法,旨在模組初始化的時候呼叫,這樣,對映的配置也在模組初始化的時候完成了。如果在一般的ASP.Net專案中,應該在全域性配置檔案Global.asax中的Application_Start方法中呼叫AutoMapper的配置方法,其他專案類似。
以後,想要新增配置資訊時,只需要定義相應的XXProfile類,然後在AutoMapperWebConfig類中新增配置檔案類就可以了。