1 前言
我喜歡造輪子,一是造的時候就是深刻學習的時候,二是造著造著,說不定某天比世面上的其它輪子都要好呢。比如造過Networksocket,也造過WebApiClient,現在我也要造一個Mapper,由於已經有好多Mapper存在,所以這個專案只能叫偏門的QMapper了。
2 QMapper的定位
2.1 約定限制
- 屬性名稱相同的才能對映
- 屬性名稱大小寫不敏感
- 不支援巢狀屬性對映
2.2 功能要求
- 無預先配置,效能要好
- 支援對映時傳入要對映的屬性名
- 支援對映時傳入忽略對映的屬性名
- 封裝的呼叫Api使用簡單
2.3 應用場景
- PO、VO、DTO相互轉換
- PO、VO、DTO相互轉換時保護一些欄位
- 根據前端提交的欄位,動態PO、VO、DTO相互轉換
2.4 使用例子
var a = new A();
var b = a.AsMap().To<B>();
var b = a.AsMap("Name","Age").To<B>();
var b = a.AsMap().Ignore(item=>item.Id).To<B>();
3 Benchmark
BenchmarkDotNet=v0.11.5, OS=Windows 10.0.17134.885 (1803/April2018Update/Redstone4)
Intel Core i3-4150 CPU 3.50GHz (Haswell), 1 CPU, 4 logical and 2 physical cores
.NET Core SDK=3.0.100-preview6-012264
[Host] : .NET Core 3.0.0-preview6-27804-01 (CoreCLR 4.700.19.30373, CoreFX 4.700.19.30308), 64bit RyuJIT
DefaultJob : .NET Core 3.0.0-preview6-27804-01 (CoreCLR 4.700.19.30373, CoreFX 4.700.19.30308), 64bit RyuJIT
| Method | Mean | Error | StdDev | Median |
|-------------------------------- |---------------:|---------------:|--------------:|---------------:|
| QMap | 201.0 ns | 4.368 ns | 11.74 ns | 198.2 ns |
| EmitMap | 832.6 ns | 42.569 ns | 119.37 ns | 780.7 ns |
| AutoMap_Singleton_Configuration | 428.1 ns | 12.006 ns | 33.86 ns | 415.0 ns |
| AutoMap_Transient_Configuration | 4,694,588.0 ns | 117,854.402 ns | 341,916.99 ns | 4,559,848.4 ns |
3.1 特殊性說明
AutoMap_Singleton_Configuration和其它三個測試條件不一樣,為了能夠進行測試,只能直接呼叫它配置好的IMapper例項,但在應用環境中,我們必須從DI或快取中根據型別對映獲取型別對應的IMapper例項,一般的快取查詢將消耗3倍數的時間。
3.2 QMap為什麼快
QMap存在必須的約定和限制,其在架構設計時就可以拋棄快取,使用泛型型別的靜態方法或靜態屬性取代快取功能,從而獲取到比使用快取更高的效能。另外,QMap在屬性型別轉換時,構造Expression時分析使用最優的轉換方法,從而在執行時的轉換邏輯包含最少的IL指令,同時將裝箱拆箱操作降低到最少。
4 github原始碼
https://github.com/xljiulang/QMapper
目前QMapper還是初期,功能少,程式碼也少,閱讀容易。