通过编译lambda表达式来创建实例(可在反射时候用,效率比反射高一些)
原文地址:https://rogerjohansson.blog/2008/02/28/linq-expressions-creating-objects/
据说编译lambda创建实例是比反射快。实际测试了一下,循环创建10,000次花的时间差不多,创建1,000,000,反射大概十几秒,lambda不到1秒。
实际使用应该没什么影响,因为一般不会出现大量创建实例的场景。不过创建生成lambda的代码还是可以学习下的。
class Program { static void Main(string[] args) { var type = typeof(List<int>); var ctor = type.GetConstructor(Type.EmptyTypes); //使用Activator var list1 = Activator.CreateInstance(type); //使用ObjectActivator var activator = GetActivator<List<int>>(ctor); var list = activator.Invoke(); Console.ReadKey(); } public delegate T ObjectActivator<out T>(params object[] args); public static ObjectActivator<T> GetActivator<T>(ConstructorInfo ctor) { ParameterInfo[] paramsInfo = ctor.GetParameters(); //create a single param of type object[] ParameterExpression param = Expression.Parameter(typeof(object[]), "args"); Expression[] argsExp = new Expression[paramsInfo.Length]; //pick each arg from the params array //and create a typed expression of them for (int i = 0; i < paramsInfo.Length; i++) { Expression index = Expression.Constant(i); Type paramType = paramsInfo[i].ParameterType; Expression paramAccessorExp = Expression.ArrayIndex(param, index); Expression paramCastExp = Expression.Convert(paramAccessorExp, paramType); argsExp[i] = paramCastExp; } //make a NewExpression that calls the //ctor with the args we just created NewExpression newExp = Expression.New(ctor, argsExp); //create a lambda with the New //Expression as body and our param object[] as arg LambdaExpression lambda = Expression.Lambda(typeof(ObjectActivator<T>), newExp, param); //compile it ObjectActivator<T> compiled = (ObjectActivator<T>)lambda.Compile(); return compiled; } }