如何移除ExpressionCache类的泛型参数以简化调用?
无泛型参数的表达式编译缓存优化实现
你可以通过将ExpressionCache重构为非泛型静态类,结合泛型方法自动推断类型参数的方式,实现无需显式指定泛型参数的简化调用。核心思路是用Delegate作为缓存值的基类型,兼容所有TSource->TDest的委托类型,再通过泛型方法自动识别具体类型。
优化后的ExpressionCache实现
public static class ExpressionCache { // 用Delegate兼容所有类型的映射委托,键为源类型+目标类型的组合 private static readonly ConcurrentDictionary<(Type SourceType, Type DestType), Delegate> _mapCache = new(); // 泛型方法自动推断TSource和TDest,无需调用时显式声明 public static Func<TSource, TDest> Compile<TSource, TDest>(Expression<Func<TSource, TDest>> map) { var key = (typeof(TSource), typeof(TDest)); // 尝试从缓存获取并转换为具体委托类型 if (_mapCache.TryGetValue(key, out var cachedDelegate) && cachedDelegate is Func<TSource, TDest> cachedFunc) { return cachedFunc; } // 编译表达式并写入缓存 var compiledFunc = map.Compile(); _mapCache[key] = compiledFunc; return compiledFunc; } }
简化调用方式
现在你可以直接使用目标语法调用,无需指定泛型参数:
var source = _context.Product.Find(productId); var dto = ExpressionCache.Compile(Maps.ProductMap)(source);
如果保留MapBuilder,修改后的方法依然可以正常工作:
public static class MapBuilder { public static TDest ToInstance<TSource, TDest>(TSource source, Expression<Func<TSource, TDest>> map) { return ExpressionCache.Compile(map)(source); } } // 原有使用方式保持不变 var dto = MapBuilder.ToInstance(source, Maps.ProductMap);
优化说明
- 类型自动推断:泛型方法
Compile<TSource, TDest>会通过传入的Expression<Func<TSource, TDest>>自动识别源类型和目标类型,无需调用时显式声明。 - 缓存兼容性:用
Delegate作为缓存值的基类型,可存储任意类型的映射委托,取出时再转换为具体的Func<TSource, TDest>,保证类型安全。 - 线程安全:保留
ConcurrentDictionary确保多线程环境下的缓存操作安全,避免重复编译。
内容的提问来源于stack exchange,提问作者clhereistian
相关产品推荐
相关产品推荐

