如何在扩展方法中获取编译时类型以简化泛型向下转型?
简化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
相关产品推荐
相关产品推荐

