如何用AutoMapper为泛型类OverridableValue<T>创建通用映射?
问题:AutoMapper中为泛型类OverridableValue配置通用映射
我有一个泛型类OverridableValue<T>,用于表示可手动覆盖的值(包含T类型的Value属性和一个标记是否为手动设置的布尔值)。该类用于内部模型中,而API的DTO只需保存值,无需关注是否为手动设置。例如以下类:
public class Test { public OverridableValue<string> Prop1 { get; set; } public OverridableValue<int> Prop2 { get; set; } } public class TestDTO { public string Prop1 { get; set; } public int Prop2 { get; set; } }
目前我可以通过以下方式创建Test与TestDTO的映射:
CreateMap<OverridableValue<string>, string>().ConvertUsing(o => o.Value); CreateMap<OverridableValue<int>, int>().ConvertUsing(o => o.Value); CreateMap<Test, TestDTO>();
但我不想为OverridableValue的每个泛型用法都添加一行映射配置,希望创建一个适用于所有泛型实例的通用映射,类似:
CreateMap<OverridableValue<T>, T>().ConvertUsing(o => o.Value);
请问是否有实现这种通用映射的方法?
解决方案
AutoMapper支持通过泛型类型定义配置全局通用映射,无需为每个具体的OverridableValue<T>重复编写配置,具体实现有两种方式:
方法一:基于泛型类型定义+通用转换器(推荐)
直接针对OverridableValue<>的泛型类型定义创建映射,搭配通用转换器实现全局规则:
// 在AutoMapper配置中添加以下代码 var overridableGenericType = typeof(OverridableValue<>); // 为所有OverridableValue<T>到T的转换配置通用规则 CreateMap(overridableGenericType, overridableGenericType.GetGenericArguments()[0]) .ConvertUsing(typeof(OverridableValueConverter<>)); // 定义通用转换器类 public class OverridableValueConverter<T> : ITypeConverter<OverridableValue<T>, T> { public T Convert(OverridableValue<T> source, T destination, ResolutionContext context) { return source.Value; } }
配置完成后,所有OverridableValue<T>类型的属性在映射到T类型时,都会自动应用这个转换规则,包括Test到TestDTO的映射会自动生效。
方法二:通过ForAllMaps自动识别配置
如果需要更灵活的属性级控制,可以用ForAllMaps遍历所有映射规则,自动识别OverridableValue<T>类型的属性并配置映射:
var config = new MapperConfiguration(cfg => { cfg.ForAllMaps((map, exp) => { foreach (var sourceProp in map.SourceType.GetProperties()) { var propType = sourceProp.PropertyType; // 判断属性是否为OverridableValue<T>的泛型实例 if (propType.IsGenericType && propType.GetGenericTypeDefinition() == typeof(OverridableValue<>)) { var targetProp = map.DestinationType.GetProperty(sourceProp.Name); if (targetProp != null) { // 配置该属性映射到对应的Value值 exp.ForMember(targetProp.Name, opt => opt.MapFrom(src => sourceProp.GetValue(src)?.GetType().GetProperty("Value").GetValue(sourceProp.GetValue(src)))); } } } }); // 添加具体的类映射 cfg.CreateMap<Test, TestDTO>(); });
内容的提问来源于stack exchange,提问作者DorBS
相关产品推荐
相关产品推荐

