如何用Lambda表达式实现反射创建对象,替代Activator.CreateInstance提升性能?
用编译后的Lambda表达式替代Activator.CreateInstance提升对象创建性能
如果你一直在用Activator.CreateInstance通过反射创建对象,肯定遇到过它的性能瓶颈——每次调用都要走反射流程,开销不小。而用编译后的Lambda表达式来生成对象实例,能把反射的开销降到最低:第一次编译Lambda后,后续调用都是直接的委托执行,性能提升非常显著。
我自己实现了一个静态工具类ClassBuilder,专门用来处理这种场景,代码完整实现如下:
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; public static class ClassBuilder { private delegate T ObjectActivator<T>(params object[] args); private static readonly Dictionary<(Type Type, Type[] ParamTypes), Delegate> _activatorCache = new Dictionary<(Type, Type[]), Delegate>(); /// <summary> /// 此函数将创建T类型的具体对象 /// </summary> /// <typeparam name="T">要返回的对象的基类或具体类型</typeparam> /// <param name="type">要创建的对象的具体类型</param> /// <param name="parameters">传递给构造函数的参数</param> /// <returns>具体对象的实例</returns> public static T CreateInstance<T>(Type type, params object[] parameters) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } // 获取给定参数的具体类型 Type[] typedArgs = parameters.Select(p => p.GetType()).ToArray(); var cacheKey = (type, typedArgs); // 优先从缓存获取已编译的激活器 if (_activatorCache.TryGetValue(cacheKey, out var activator)) { return ((ObjectActivator<T>)activator)(parameters); } // 根据参数获取对应的构造函数 ConstructorInfo ctor = type.GetConstructor(typedArgs); if (ctor != null) { // 创建并编译激活器Lambda ObjectActivator<T> createdActivator = GetActivator<T>(ctor); // 存入缓存复用 _activatorCache[cacheKey] = createdActivator; return createdActivator(parameters); } else { throw new ArgumentException($"无法找到类型 {type.FullName} 匹配参数类型的构造函数"); } } private static ObjectActivator<T> GetActivator<T>(ConstructorInfo ctor) { var paramsInfo = ctor.GetParameters(); // 定义Lambda的输入参数:object[]类型的参数数组 var paramExpr = Expression.Parameter(typeof(object[]), "args"); var argsExpr = new Expression[paramsInfo.Length]; for (int i = 0; i < paramsInfo.Length; i++) { // 从参数数组中取出对应位置的元素,并转换为构造函数所需的类型 var indexExpr = Expression.Constant(i); var paramAccessorExpr = Expression.ArrayIndex(paramExpr, indexExpr); var paramCastExpr = Expression.Convert(paramAccessorExpr, paramsInfo[i].ParameterType); argsExpr[i] = paramCastExpr; } // 构建调用构造函数的表达式 var newExpr = Expression.New(ctor, argsExpr); // 编译表达式为委托 var lambda = Expression.Lambda<ObjectActivator<T>>(newExpr, paramExpr); return lambda.Compile(); } }
关键细节说明
- 委托定义:
ObjectActivator<T>委托用来匹配带可变参数的构造函数调用,让我们可以用统一的方式传递参数并创建实例。 - 缓存机制:新增的
_activatorCache字典用来缓存已编译的委托,避免同一类型、同一参数组合的实例重复编译Lambda,进一步降低开销。 - Lambda编译核心:
GetActivator<T>方法通过Expression API构建调用目标构造函数的表达式,然后编译成委托。这一步只在第一次创建对应类型实例时执行,后续都是直接调用委托。
使用示例
你可以像这样调用这个工具类,替代原来的Activator.CreateInstance:
// 假设有一个类:public class MyClass { public MyClass(string name, int age) { ... } } MyClass instance = ClassBuilder.CreateInstance<MyClass>(typeof(MyClass), "张三", 25);
这个实现的性能优势在高频调用场景下会非常明显,完全可以替代Activator.CreateInstance的反射调用。
内容的提问来源于stack exchange,提问作者cheikh ndiaye
相关产品推荐
相关产品推荐

