如何用IValueResolver实现非泛型到开放泛型的AutoMapper映射?
解决AutoMapper非泛型到开放泛型的反向映射问题
要实现SerializableFoo到Foo<T>的反向映射,核心是在运行时根据SerializableFoo的TypeAQN确定泛型参数T的具体类型,再完成转换。你之前的报错是因为AutoMapper无法从非泛型源自动推断开放泛型目标的具体类型参数,直接配置成员映射会导致泛型参数数量不匹配。
正确实现方案
使用ITypeConverter替代IValueResolver,它能更灵活地处理运行时类型推断和完整对象转换:
1. 实现自定义类型转换器
public sealed class SerializableFooToFooConverter : ITypeConverter<SerializableFoo, object> { public object Convert(SerializableFoo source, object destination, ResolutionContext context) { if (string.IsNullOrEmpty(source.TypeAQN)) throw new InvalidOperationException("TypeAQN cannot be null or empty"); // 加载目标泛型参数类型 var targetType = Type.GetType(source.TypeAQN); if (targetType == null) throw new TypeLoadException($"Cannot load type from AQN: {source.TypeAQN}"); // 构造具体的Foo<T>类型 var fooGenericType = typeof(Foo<>).MakeGenericType(targetType); var fooInstance = Activator.CreateInstance(fooGenericType); // 反序列化Data到目标类型并赋值(这里假设你的Data是字符串形式,可根据实际序列化方式调整) var value = string.IsNullOrEmpty(source.Data) || source.Data == "<null>" ? null : Convert.ChangeType(source.Data, targetType); fooGenericType.GetProperty(nameof(Foo<object>.Value))?.SetValue(fooInstance, value); return fooInstance; } }
2. 配置AutoMapper映射
// 正向映射保持不变 this.CreateMap(typeof(Foo<>), typeof(SerializableFoo), MemberList.None) .ForMember(nameof(SerializableFoo.TypeAQN), opt => opt.MapFrom(typeof(TypeAQNValueResolver<>))) .ForMember(nameof(SerializableFoo.Data), opt => opt.MapFrom(typeof(DataValueResolver<>))); // 反向映射:使用类型转换器处理开放泛型转换 this.CreateMap(typeof(SerializableFoo), typeof(Foo<>)) .ConvertUsing(typeof(SerializableFooToFooConverter));
3. 使用方式
转换时需要明确指定目标具体泛型类型(或通过运行时类型动态调用):
// 示例:已知目标类型为Foo<int> var serializableFoo = new SerializableFoo { TypeAQN = typeof(int).AssemblyQualifiedName, Data = "123" }; var fooInt = mapper.Map<Foo<int>>(serializableFoo); // 动态类型场景 var targetType = typeof(Foo<>).MakeGenericType(typeof(string)); var fooDynamic = mapper.Map(serializableFoo, typeof(SerializableFoo), targetType);
关键说明
- 为什么不用
IValueResolver?因为IValueResolver需要明确的源和目标泛型参数,而反向映射中目标类型的泛型参数只有运行时才能确定,ITypeConverter可以直接处理object类型的目标,再通过反射构造具体泛型实例。 - 序列化/反序列化逻辑可按需调整:示例中用
Convert.ChangeType处理简单类型,若用JSON等序列化库,替换为对应反序列化逻辑即可(比如JsonSerializer.Deserialize(source.Data, targetType))。
内容的提问来源于stack exchange,提问作者Sebastian Schumann
相关产品推荐
相关产品推荐

