龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > asp.net编程 >

.NET比较表达式树对性能影响

时间:2009-12-21 11:47来源:未知 作者:admin 点击:
分享到:
原题 :日常应用中我们常常会和一些数据实体类打交道。现在假设我们的数据实体类里面定义了许多public的属性。请用Expression Tree实现一个动态逻辑,可以更新任意一种数据实体类的集

      原题:日常应用中我们常常会和一些数据实体类打交道。现在假设我们的数据实体类里面定义了许多public的属性。请用Expression Tree实现一个动态逻辑,可以更新任意一种数据实体类的集合,比如List<Book>, List<Employee>等等中每一个元素的指定属性。比如我要对一个集合中所有Book元素的Author属性进行更新,您的程序就可以这样调用:

    List<Book> books = …

    SetAllProperty(books, “Author”, “Ninputer”);

    当然您写的方法不知道Book类型,也不知道我要更新哪个属性,它应该能动态地支持任意的实体类集合。

    首先我想到的就是遍历实体的属性,找对就修改的属性,然后调用SetValue方式就OK,代码也不多,如下: 

public List<T> SetAllProperty(List<T> t, object propertyName, object propertyValue)
         {
             
if (null == t||null ==propertyName ||null ==propertyValue )
             {
                 
return null ;
             }
             
for (int i = 0; i < t.Count; i++)
             {
                 PropertyInfo[] proAs 
= t[i].GetType().GetProperties();
                 
foreach (PropertyInfo proA in proAs)
                 {
                     
if (!proA.CanRead &&!proA .CanWrite ) continue;

                     
if (proA.Name.ToLower()==propertyName .ToString ().ToLower ())
                     {
                         proA.SetValue(t[i], propertyValue , 
null);
                     }
                 
                 }
             }
             
return t;
         }

    
      问题:上面的代码理论上和实际操作上都能够很好的完成练习题,但有个性能问题,如果这个实体集特别大的时候,比如一百万或者更多,此时就会特别耗时。于时我在脑袋的指点下,花了大半天时间终于有所结果:

      版本一:结果都是正确的,问题时,这种写法比遍历属性赋值方式更慢。问题就在于LambdaExpression lambda = Expression.Lambda(call, parameter, value);var exp = lambda.Compile();这两条语句上,这个表达式经过Compile()后会生成一个Delegate,Compile方法在内部使用了Emit,而问题就出了DynamicInvoke上面,DynamicInvoke方法其本质与反射调用差不多。

public List<T> ExpressionTree<T>(List<T> collection, object propertyName, string   propertyValue)
        {
            ParameterExpression parameter 
= Expression.Parameter(typeof(T), "x");

            ParameterExpression value 
= Expression.Parameter(typeof(string  ), "propertyValue");

            MethodInfo setter 
= typeof(T).GetMethod("set_"+propertyName );

            MethodCallExpression call 
= Expression.Call(parameter, setter, value);

            LambdaExpression lambda 
= Expression.Lambda(call, parameter, value);
            var exp 
= lambda.Compile();
            
for (int i = 0; i < collection.Count; i++)
            {
                exp.DynamicInvoke(collection[i], propertyValue);

            }
            
return collection;
        }

精彩图集

赞助商链接