ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

使用表达式树创建对象

2021-09-15 17:04:28  阅读:164  来源: 互联网

标签:string lamdaParameterExpressions 使用 创建对象 static constructor var Expression 表达式


使用表达式树创建对象

转载:使用表达式树创建对象 - 不夜橙 - 博客园 (cnblogs.com)

 

原来程序中的代码:

1 2 3 4 public static T GetInstance<T>() where T : new()         {             return new T();         }

需要扩展这个方法支持参数传递。可惜泛型约束不支持指定构造函数参数,那只好使用对象反射了。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class A     {         public A(string A)         {                       }           public string P1 { get; set; }                  }     //反射创建对象A Activator.CreateInstance(t, "sss");

 

这样的话对象创建速度一下会变得很慢吧。正好想到 ExpressionTree,使用Expression.New并且缓存Expression方式应该可以提高些速度。正好找到了相关用法 http://geekswithblogs.net/mrsteve/archive/2012/01/11/csharp-expression-trees-create-instance-from-type-extension-method.aspx ,核心代码如下

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 public static Func<string, T> GetExpression<T>()       {           var argumentType = new[] { typeof(string) };           // Get the Constructor which matches the given argument Types:           var constructor = typeof(T).GetConstructor(               BindingFlags.Instance | BindingFlags.Public,               null,               CallingConventions.HasThis,               argumentType,               new ParameterModifier[0]);             // Get a set of Expressions representing the parameters which will be passed to the Func:           var lamdaParameterExpressions = GetLambdaParameterExpressions(argumentType).ToArray();             // Get a set of Expressions representing the parameters which will be passed to the constructor:           var constructorParameterExpressions = GetConstructorParameterExpressions(               lamdaParameterExpressions,               argumentType).ToArray();             // Get an Expression representing the constructor call, passing in the constructor parameters:           var constructorCallExpression = Expression.New(constructor, constructorParameterExpressions);             // Compile the Expression into a Func which takes three arguments and returns the constructed object:           var constructorCallingLambda = Expression               .Lambda<Func<string, T>>(constructorCallExpression, lamdaParameterExpressions)               .Compile();           return constructorCallingLambda;         }         private static IEnumerable<ParameterExpression> GetLambdaParameterExpressions(Type[] argumentTypes)       {           for (int i = 0; i < argumentTypes.Length; i++)           {               yield return Expression.Parameter(typeof(object), string.Concat("param", i));           }       }         private static IEnumerable<UnaryExpression> GetConstructorParameterExpressions(   ParameterExpression[] lamdaParameterExpressions,   Type[] constructorArgumentTypes)       {           for (int i = 0; i < constructorArgumentTypes.Length; i++)           {               // Each parameter passed to the lambda is of type object, so we need to convert it into               // the appropriate type for the constructor:               yield return Expression.Convert(lamdaParameterExpressions[i], constructorArgumentTypes[i]);           }       }

 

试试有何提升:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 static void Main(string[] args)         {             var t = typeof (A);             var count = 10000000;               var expression = GetExpression<A>();             var ts2 = Timer.Time(() =>             {                 var o = expression.Invoke("sss");             }, count);                 var ts= Timer.Time(() =>             {                 var o = Activator.CreateInstance(t, "sss");             }, count);             var ts3 = Timer.Time(() =>             {                 var o = new A("SSS");             }, count);               Console.WriteLine("{0}:{1} ", "Direct", ts3.Milliseconds);             Console.WriteLine("{0}:{1}", "Activator.CreateInstance", ts.Milliseconds);             Console.WriteLine("{0}:{1}", "Expression", ts2.Milliseconds);                           Console.ReadLine();         }

结果:

image

 

结论

使用Expression代替Activator.CreateInstance加快对象创建速度。另外使用Expression&Delegate.CreateDelegate代替传统C#反射加速属性和方法的调用

标签:string,lamdaParameterExpressions,使用,创建对象,static,constructor,var,Expression,表达式
来源: https://www.cnblogs.com/Insist-Y/p/15273000.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有