You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 16:20:12