关于AutoMapper AllowAdditiveTypeMapCreation未合并映射的疑问
设置Internal().AllowAdditiveTypeMapCreation = true;后,我原本预期以下两段映射配置会合并:
CreateMap<Source, Destination>() .ForMember(dest => dest.Id, opt => opt.Ignore()); CreateMap<Source, Destination>() .ForMember(dest => dest.Name, opt => opt.Ignore());
合并结果应为:
CreateMap<Source, Destination>() .ForMember(dest => dest.Id, opt => opt.Ignore()) .ForMember(dest => dest.Name, opt => opt.Ignore());
但实际最后一次CreateMap()会覆盖之前的配置,测试时提示dest.Id未映射。即使将两段CreateMap()放在不同Profile中,仍会抛出相同异常。
我对AllowAdditiveTypeMapCreation的理解是否有误?目前没有官方文档,仅能从源码找到简要说明:
允许同一映射存在于不同Profile中。默认会抛出异常,设为true则合并映射。
使用场景
我需要实现的需求是:多组Source/Destination类型对存在共同属性需要忽略,示例类型如下:
public class Source1 { public DateTime CreationDate { get; set; } } public class Destination1 { public DateTime CreationDate { get; set; } } public class Source2 { public DateTime CreationDate { get; set; } } public class Destination2 { public DateTime CreationDate { get; set; } } public class Source3 { public DateTime CreationDate { get; set; } } public class Destination3 { public DateTime CreationDate { get; set; } public string ExtraProperty { get; set; } // 后续需要忽略的额外属性 }
这些类型对通过接口或Attribute标记后,用反射获取到数组中(模拟结果如下):
var listSourceDestination = new[] { new KeyValuePair<Type, Type>(typeof(Source1), typeof(Destination1)), new KeyValuePair<Type, Type>(typeof(Source2), typeof(Destination2)), new KeyValuePair<Type, Type>(typeof(Source3), typeof(Destination3)) };
我先循环遍历数组,用非泛型CreateMap()统一忽略共同属性:
foreach (var pair in listSourceDestination) { CreateMap(pair.Key, pair.Value) .ForMember("CreationDate", opt => opt.Ignore()); }
之后需要单独忽略Destination3的ExtraProperty,于是使用泛型CreateMap<,>():
CreateMap<Source3, Destination3>() .ForMember(dest => dest.ExtraProperty, opt => opt.Ignore());
我原本期望这两次创建的Source3/Destination3映射会合并为:
CreateMap<Source3, Destination3>() .ForMember(dest => dest.CreationDate, opt => opt.Ignore()) .ForMember(dest => dest.ExtraProperty, opt => opt.Ignore());
但实际是第二次的CreateMap覆盖了第一次的配置,导致CreationDate未被忽略。
映射继承尝试
尝试使用映射继承的方式解决:先定义基类,让所有类型继承基类:
public abstract class BaseSource { public DateTime CreationDate { get; set; } } public abstract class BaseDestination { public DateTime CreationDate { get; set; } } public class Source1 : BaseSource {} public class Destination1 : BaseDestination {} public class Source2 : BaseSource {} public class Destination2 : BaseDestination {} public class Source3 : BaseSource {} public class Destination3 : BaseDestination { public string ExtraProperty { get; set; } }
同样使用之前的类型对数组,先创建基类映射:
CreateMap<BaseSource, BaseDestination>() .ForMember(dest => dest.CreationDate, opt => opt.Ignore()); // 也可使用非泛型版本 // CreateMap(typeof(BaseSource), typeof(BaseDestination)) // .ForMember("CreationDate", opt => opt.Ignore());
然后循环遍历派生类型对,配置继承基类映射:
foreach (var pair in listSourceDestination) { CreateMap(pair.Key, pair.Value) .IncludeBase(typeof(BaseSource), typeof(BaseDestination)); }
最后单独配置Source3/Destination3忽略额外属性:
CreateMap<Source3, Destination3>() // 若取消注释此行才能生效,说明映射被覆盖而非合并,与我对AllowAdditiveTypeMapCreation的理解不符 // .IncludeBase(typeof(BaseSource), typeof(BaseDestination)) .ForMember(dest => dest.ExtraProperty, opt => opt.Ignore());
如果不重复添加IncludeBase,基类的忽略配置会丢失,这说明第二次CreateMap仍然覆盖了之前的配置,并非合并。
内容的提问来源于stack exchange,提问作者Twisted Whisper

