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

AutoMapper技术问题:如何通过构造函数映射Class<T>到Class<T>

解决Request同类型映射时的构造函数实例化问题

问题核心

当前代码报错的根源是dest参数始终为null——在AutoMapper的ConvertUsing自定义转换逻辑中,框架不会预先实例化目标对象,因此无法通过dest.GetType()获取泛型参数。

修复方案

直接从源对象src的类型中提取泛型参数,而非依赖null的dest对象。同时优化反射操作的稳定性:

CreateMap(typeof(Request<>), typeof(Request<>))
    .ConvertUsing((src, dest, context) =>
    {
        // 从源对象类型提取泛型参数
        var srcType = src.GetType();
        var genericTypes = srcType.GetGenericArguments();
        
        // 提取UserId和RequestId,用nameof避免硬编码
        var userId = srcType.GetProperty(nameof(Request<object>.UserId))?.GetValue(src) as string 
            ?? throw new ArgumentException("UserId has no value");
        var requestId = srcType.GetProperty(nameof(Request<object>.RequestId))?.GetValue(src) as string 
            ?? throw new ArgumentException("RequestId has no value");

        // 创建带参数的目标实例
        var destinationType = typeof(Request<>).MakeGenericType(genericTypes);
        return Activator.CreateInstance(destinationType, new RequestContext(userId, requestId)) as object;
    });

更优替代方案

如果仅需控制目标对象的构造逻辑(无复杂转换逻辑),建议使用AutoMapper专门的ConstructUsing方法,更贴合场景:

CreateMap(typeof(Request<>), typeof(Request<>))
    .ConstructUsing((src, context) =>
    {
        var srcType = src.GetType();
        var genericTypes = srcType.GetGenericArguments();
        var userId = srcType.GetProperty(nameof(Request<object>.UserId))?.GetValue(src) as string 
            ?? throw new ArgumentException("UserId has no value");
        var requestId = srcType.GetProperty(nameof(Request<object>.RequestId))?.GetValue(src) as string 
            ?? throw new ArgumentException("RequestId has no value");
        
        var destinationType = typeof(Request<>).MakeGenericType(genericTypes);
        return Activator.CreateInstance(destinationType, new RequestContext(userId, requestId));
    });

额外优化建议

  • 提前缓存Request<>的UserId和RequestId属性信息,避免每次转换重复反射,提升性能。
  • 若Request<T>实现了通用接口(如IRequest),可直接通过接口访问属性,彻底消除反射:
    // 定义通用接口
    public interface IRequest
    {
        string UserId { get; }
        string RequestId { get; }
    }
    
    public class Request<T> : IRequest { ... }
    
    // 转换逻辑简化
    var request = src as IRequest;
    var userId = request?.UserId ?? throw new ArgumentException("UserId has no value");
    

内容的提问来源于stack exchange,提问作者Jacob Roberts

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 09:20:33