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

如何在扩展方法中获取编译时类型以简化泛型向下转型?

简化AutoMapper向下转型扩展方法的实现

当然可以实现你想要的简化调用方式!C#的泛型推断机制能帮我们自动确定TParent的类型,完全不需要手动指定。

正确的简化实现

我们可以利用扩展方法的this参数类型让编译器自动推断TParent,只保留TChild作为显式指定的泛型参数。同时,为了避免每次调用重复创建MapperConfiguration和IMapper实例(会影响性能),还可以加入缓存机制优化:

using AutoMapper;
using System.Collections.Generic;

public static class DowncastExtensions
{
    // 缓存已创建的映射器,避免重复初始化配置
    private static readonly Dictionary<(Type ParentType, Type ChildType), IMapper> _mapperCache = 
        new Dictionary<(Type, Type), IMapper>();

    public static TChild Downcast<TChild>(this TParent parent)
        where TChild : class, TParent
    {
        var parentType = typeof(TParent);
        var childType = typeof(TChild);
        var cacheKey = (parentType, childType);

        // 优先从缓存获取映射器
        if (!_mapperCache.TryGetValue(cacheKey, out var mapper))
        {
            var config = new MapperConfiguration(cfg => 
                cfg.CreateMap(parentType, childType));
            mapper = config.CreateMapper();
            _mapperCache[cacheKey] = mapper;
        }

        return mapper.Map<TChild>(parent);
    }
}

调用方式

现在你可以像预期的那样简化调用,编译器会自动从parent的编译时类型推断出TParent:

var parent = new Parent { Name = "Bob" };
var child = parent.Downcast<Child>();

// 验证属性映射正确性
Assert.AreEqual(parent.Name, child.Name);

为什么你的原始想法无法直接实现?

你提到的where TParent : caller是无效的C#语法,C#中没有这类约束直接绑定调用者类型。但借助泛型推断,编译器会自动根据扩展方法的this参数(即调用方法的对象)的类型,确定TParent的具体类型,从而达到你想要的简化效果。

额外优化建议

  • 如果父类和子类有固定映射规则,建议提前在AutoMapper全局配置中注册,而非每次调用都创建新配置,性能会更优。
  • 代码中添加的where TChild : class, TParent约束,能确保TChild确实是TParent的子类,避免无效类型转换。

内容的提问来源于stack exchange,提问作者Emirhan Özlen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:36:44