上一節是 AutoMapper 在注入 Controller 建構子所做的準備工作。這節要看如何運作轉換類別對應。
上節準備工作最末,其中一個設定是 prfile 的設定,會將剛剛 MapperConfigurationExpression 的 List _profiles欄位 轉換到 AutoMapper.MapperConfiguration 的 ProfileMap[] Profiles 類別陣列裡。
之後會將此 ProfileMap 逐一取出,做 ProfileMap.BuildTypeMap:
private void BuildTypeMap(IGlobalConfiguration configurationProvider, ITypeMapConfiguration config)
{
var typeMap = new TypeMap(config.SourceType, config.DestinationType, this, config.IsReverseMap);
config.Configure(typeMap);
configurationProvider.RegisterTypeMap(typeMap);
}
而在 產生 TypeMap 實體時, 建構子會將目的類別的成員資訊取出,包含成員的 Type 屬性,與 命名 屬性。
public TypeMap(Type sourceType, Type destinationType, ProfileMap profile, bool isReverseMap = false)
{
Types = new(sourceType, destinationType);
Profile = profile;
SourceTypeDetails = profile.CreateTypeDetails(sourceType);
DestinationTypeDetails = profile.CreateTypeDetails(destinationType);
var sourceMembers = new List<MemberInfo>();
foreach (var destinationProperty in DestinationTypeDetails.WriteAccessors)
{
sourceMembers.Clear();
var propertyType = destinationProperty.GetMemberType();
if (profile.MapDestinationPropertyToSource(SourceTypeDetails, destinationType, propertyType, destinationProperty.Name, sourceMembers, isReverseMap))
{
AddPropertyMap(destinationProperty, propertyType, sourceMembers);
}
}
}
之後主要會有二個步驟:
Step1:
欄位命名做對應,取出對應來源類別的相同命名的屬性之 System.Reflection.MemberInfo,轉存到 PropertyMap,並加入到 TypeMap 的 Dictionary<string, PropertyMap> _propertyMaps裡。
如果有擴充功能之設定,會依照設定加入 TypeMap 之設定。 目的與來源類別的互相轉換組合會再以 TypeMap 的封裝加入到 AutoMapper.MapperConfiguration 的 Dictionary<TypePair, TypeMap> _configuredMaps裡。
Step2:
執行每份 _configuredMaps 中對應 typeMap.Seal -> TypeMap.CreateMapperLambda 。
基本上,要組出的轉換函式會先去 new 目的類別實體,然後對每個 來源類別成員的值 指派到 目的類別對應欄位,如果轉換型別過程找不到來源類別的成員,就使用目的成員的預設值。但這是最基本的 apply。
最後會將 Lambda Expression 指派到 typeMap.MapExpression中。
之後會將 _configuredMaps 經過設定檢查後指派到 _resolvedMaps 。
當執行:
_mapper.Map<Product, ProductDTO>(product)
會透過 MapCore 函式, 再呼叫 AutoMapper.MapperConfiguration 的 GetExecutionPlan , 進而呼叫之前準備工作時委派的 BuildExecutionPlan。 隨後執行 ResolveTypeMap 將欲做 Mapping 轉換的 TypeMap 取出,
然後傳入此 TypeMap 實體給 GenerateTypeMapExpression 函式。接著執行 TypeMap.MapExpression,將目的類別實體產出。
AutoMapper 有許多複雜且多情境的轉換,以上先以基本款轉換做運作說明。