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

C#如何实现支持预定义手动映射规则的通用泛型Mapper?

问题场景

多个类包含重复的对象映射逻辑,为遵循DRY原则避免冗余代码,计划创建抽象基类封装通用逻辑,基类中包含如下泛型实体获取方法:

public TEntity GetEntity(Result<TServiceClientEntity> res) 
{
    entity = MappingProfiles.TryMap(res.Value);
    // 此处编写结果处理的通用逻辑
    return entity;
}

用到的泛型Result类定义如下:

public class Result<T>
{
    public T Value{ get; set; }
    // 其余业务属性定义
}

当前卡在MappingProfiles的泛型TryMap实现上,现有写法无法根据传入的实际类型自动匹配对应的手写Map方法:

public static class MappingProfiles
{
    public static T2 TryMap<T,T2>(T t) 
    {
        return (T2)Map((Real_T_type)t); // 硬编码实际类型的写法无法适配泛型场景
    }

    public static ExampleTo Map(ExampleFrom from)
    {
        return new ExampleTo
        {
            exapleValue = from.exapleValue
        };
    }
}

补充要求:TryMap泛型方法必须调用预先定义好的手动Map方法完成映射,不能用自动映射类库替代手写逻辑。


实现方案

用预注册映射委托的方式实现,无额外反射开销,可完全复用已写好的手动Map方法,具体实现如下:

  1. 在MappingProfiles中新增静态字典做映射缓存,键为「源类型+目标类型」的元组,值为对应的映射委托
  2. 在静态构造函数中把所有手写的Map方法注册到缓存字典中
  3. TryMap方法运行时根据传入的泛型类型从缓存取对应委托执行即可,找不到匹配映射时可按业务需求抛出明确异常或返回默认值

完整可运行代码:

public static class MappingProfiles
{
    // 映射委托缓存,键格式为(源类型, 目标类型)
    private static readonly Dictionary<(Type From, Type To), Delegate> _mapperCache = new();

    // 类首次加载时注册所有手写映射方法
    static MappingProfiles()
    {
        // 注册已写好的ExampleFrom -> ExampleTo映射
        Register<ExampleFrom, ExampleTo>(Map);
        // 后续新增手写Map方法,在此处追加一行Register调用即可
    }

    // 映射注册辅助方法
    public static void Register<TFrom, TTo>(Func<TFrom, TTo> mapFunc)
    {
        _mapperCache[(typeof(TFrom), typeof(TTo))] = mapFunc;
    }

    public static T2 TryMap<T, T2>(T source)
    {
        var typeKey = (typeof(T), typeof(T2));
        if (_mapperCache.TryGetValue(typeKey, out var mapDelegate))
        {
            return ((Func<T, T2>)mapDelegate)(source);
        }
        // 未找到映射的处理逻辑,可按需调整为返回默认值、记录日志等
        throw new InvalidOperationException($"未注册从{typeof(T).Name}到{typeof(T2).Name}的映射规则");
    }

    // 原有手写Map方法无需任何修改
    public static ExampleTo Map(ExampleFrom from)
    {
        return new ExampleTo
        {
            exapleValue = from.exapleValue
        };
    }
}

方案说明

  • 所有映射逻辑完全复用你预先写好的手动Map方法,没有自动生成的映射逻辑,完全符合要求
  • 注册逻辑仅在类首次加载时执行一次,后续调用直接取委托执行,性能和直接调用手写方法几乎无差异
  • 该实现可以直接配合你之前写的抽象基类泛型方法使用,不需要修改基类的任何逻辑,通用结果处理代码可以正常复用
  • 如果不想每次新增映射都手动写注册代码,也可以加一段启动时反射扫描的逻辑,自动识别MappingProfiles类中命名为Map、入参和返回值符合规则的方法自动注册,手动注册的方式可控性更高,可根据项目规模选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 10:36:24