[非專業翻譯] Mapster - 配置位置

玩雙截棍的熊貓發表於2021-06-26

系列介紹

[非專業翻譯] 是對沒有中文文件進行翻譯的系列部落格,文章由機翻和譯者自己理解構成,和原文相比有所有不同,但意思基本一致。

因個人能力有限,如有謬誤之處還請指正,多多包涵。

正文

本文將說明 Mapster 中的 配置位置

入口

對映配置應該只初始化並且只進行一次配置。因此在編寫程式碼的時候不能將對映配置和對映呼叫放在同一個地方。

例如下面的例子,執行將會丟擲一個異常:

config.ForType<Poco, Dto>().Ignore("Id");
var dto1 = poco1.Adapt<Dto>(config);

config.ForType<Poco, Dto>().Ignore("Id"); //<--- 這裡將丟擲異常,因為在這之前已經觸發過了對映
var dto2 = poco2.Adapt<Dto>(config);

所以,在編寫程式碼時應該將對映配置和對映呼叫分開,將對映配置放到程式的入口,例如:

  • Main 方法
  • Global.asax.cs
  • Startup.cs
// Application_Start in Global.asax.cs
config.ForType<Poco, Dto>().Ignore("Id");
// in Controller class
var dto1 = poco1.Adapt<Dto>(config);
var dto2 = poco2.Adapt<Dto>(config);

保證配置例項和對映配置在同一位置

將配置例項和對映配置分開,可能會導致程式碼處於不同的位置,在程式碼編寫過程中可能會出現遺漏之類的問題。

使用 Fork 函式可以使配置例項與對映配置在同一位置:

var dto = poco.Adapt<Dto>(
	config.Fork(forked => forked.ForType<Poco, Dto>().Ignore("Id"));

不用擔心效能問題,只有第一次使用配置例項時會編譯,之後的呼叫將從快取中獲取。

在泛型類或方法中使用 Fork

Fork 方法預設使用檔名、行號作為鍵值。但是如果在在泛型類或泛型方法中呼叫Fork方法,必須指定鍵和型別全名稱,防止 Fork 從不同的型別引數返回無效的配置。

IQueryable<TDto> GetItems<TPoco, TDto>()
{
    var forked = config.Fork(
        f => f.ForType<TPoco, TDto>().Ignore("Id"), 
        $"MyKey|{typeof(TPoco).FullName}|{typeof(TDto).FullName}");
    return db.Set<TPoco>().ProjectToType<TDto>(forked);
}

不同的程式集

對映配置處於多個不同的程式集是比較常見的情況。

也許你的域程式集有一些對映到域物件的規則,而你的 web api 有一些特定的規則來對映到您的 api 約定。

Scan 方法

Mapster 支援掃描程式集註冊對映配置,可以幫助你快速註冊對映配置並減小忘記編碼註冊配置的機率。

在某些特定的情況下可以順序註冊程式集,以達到重寫對映配置的目的。

掃描程式集註冊對映配置非常簡單,只需要在程式集中建立一個或多個 IRegister 的實現,然後呼叫 TypeAdapterConfig 例項的 Scan 方法即可:

public class MyRegister : IRegister
{
	public void Register(TypeAdapterConfig config)
	{
		config.NewConfig<TSource, TDestination>();

		//OR to create or enhance an existing configuration
		config.ForType<TSource, TDestination>();
	}
}

使用全域性配置例項掃描程式集中的配置註冊器:

TypeAdapterConfig.GlobalSettings.Scan(assembly1, assembly2, assemblyN)

或使用特定的配置例項掃描程式集中的配置註冊器:

var config = new TypeAdapterConfig();
config.Scan(assembly1, assembly2, assemblyN);

Apply 方法

如果你使用的是其它 程式集掃描庫(如 MEF ), 那麼你可以呼叫配置例項的 Apply 方法將對映配置註冊器新增到配置例項中:

var registers = container.GetExports<IRegister>();
config.Apply(registers);

Apply 方法允許你選擇某些 對映配置註冊器 新增到 配置例項 中,而不是像 Scan 方法把程式集裡的所有 對映配置註冊器 新增到 配置例項 中:

var register = new MockingRegister();
config.Apply(register);

特性標籤

Mapster 支援通過為型別增加 特性標籤 的方式 新增型別對映配置:

[AdaptTo(typeof(StudentDto), PreserveReference = true)]
public class Student { 
    ...
}

相關文章