如何使用AutoMapper实现动态映射?
解决AutoMapper动态映射外部类型的问题
问题分析
你遇到的错误根源有两个:
- 泛型
CreateMap的局限性:泛型版本CreateMap<TSource, TDest>要求目标类型TDest是编译时已知的类型,而你传入的是运行时通过反射获取的myType,不符合泛型的使用规则。 ForMember表达式不合法:AutoMapper的ForMember方法需要接收能直接指向目标属性的表达式树,你用dest=> dest.GetType().GetProperties(...)这种反射动态获取属性的方式,无法被AutoMapper解析为合法的成员访问路径,导致它无法识别目标属性,从而抛出配置异常。
解决方案
利用AutoMapper的非泛型API,结合目标类型固定的命名规则(如ProductType的属性均为ProductTypeXXX格式),批量创建映射规则,无需逐个手动配置:
代码实现
using System.Linq; using AutoMapper; // 从外部程序集中筛选符合规则的目标类型(这里以名称以"Type"结尾为例,可根据实际调整筛选条件) var targetTypes = Assemblies.ExportedTypes .Where(t => t.Name.EndsWith("Type") && t.IsClass && !t.IsAbstract); var config = new MapperConfiguration(cfg => { foreach (var targetType in targetTypes) { // 使用非泛型CreateMap创建从TypeTableUpsert到目标类型的映射 var mappingExpr = cfg.CreateMap(typeof(TypeTableUpsert), targetType); // 按命名规则匹配并配置属性映射 // 映射TypeID → {目标类型名}ID(如ProductTypeID) var idPropName = $"{targetType.Name}ID"; mappingExpr.ForMember(idPropName, opt => opt.MapFrom(src => src.TypeID)); // 映射TypeName → {目标类型名}Name(如ProductTypeName) var namePropName = $"{targetType.Name}Name"; mappingExpr.ForMember(namePropName, opt => opt.MapFrom(src => src.TypeName)); // 映射TypeCode → {目标类型名}Code(如ProductTypeCode) var codePropName = $"{targetType.Name}Code"; mappingExpr.ForMember(codePropName, opt => opt.MapFrom(src => src.TypeCode)); // 映射TypeDescription → {目标类型名}Description(如ProductTypeDescription) var descPropName = $"{targetType.Name}Description"; mappingExpr.ForMember(descPropName, opt => opt.MapFrom(src => src.TypeDescription)); } }); // 验证映射配置(开发环境建议启用,生产环境可注释) config.AssertConfigurationIsValid(); // 创建Mapper实例 var mapper = config.CreateMapper();
关键说明
- 非泛型API适配动态类型:非泛版
CreateMap直接接收Type对象,完美适配运行时动态获取的外部类型,无需编译时确定类型。 - 命名规则驱动映射:利用目标类型属性的固定命名规律,动态拼接属性名称并传递给
ForMember,这是AutoMapper支持的合法配置方式,避免了表达式树解析失败的问题。 - 自动兼容新增类型:未来新增的外部类型只要符合当前命名规则,无需修改映射代码,就能自动被纳入映射配置。
映射使用示例
当需要执行映射时,使用非泛版Map方法:
// 动态获取目标类型 Type targetType = Assemblies.ExportedTypes.Single(t => t.Name == "ProductType"); // 构造DTO实例 var upsertDto = new TypeTableUpsert { TypeID = 1, TypeName = "Test Product", TypeCode = "TP001", TypeDescription = "Test Description" }; // 执行动态映射 var targetInstance = mapper.Map(upsertDto, typeof(TypeTableUpsert), targetType);
内容的提问来源于stack exchange,提问作者RvRaziel
相关产品推荐
相关产品推荐

