任意两个对象赋值,用Spring.Objects.ObjectWrapper效率比直接反射还慢?

 任意两个对象,对他们存在相同的字段赋值,字段包括普通property,其他类对象,父类的property。由于是任意对象,不知道类型

,因此一般的做法是直接调用反射,spring.net内部封装了任意对象赋值的方法,但是经过我的测试,发现它的速度比直接反射还慢,不知

道是自己哪里没有优化,还是方法执行有问题,粗略看了一下spring.net内部源代码,发现它自己实现了表达式树和AST来解析它的包装对象,

没太看明白,如果有谁之前研究过,可以分享一些技术文章出来。

本次用直接反射,Spring.net的ObjectWrapper和jeffreyzhao的FastReflectionLib http://www.codeplex.com/FastReflectionLib进行赋值的

效率比较。

直接反射代码如下:

直接反射代码
        /// <summary>
        
/// 把原始对象的值赋值给目标对象
        
/// </summary>
        
/// <param name="originObj">原始对象</param>
        
/// <param name="targetObj">目标对象</param>
        public static void Fill(object originObj, object targetObj)
        {
            PropertyInfo[] properties 
= originObj.GetType().GetProperties();

            
foreach (PropertyInfo item in properties)
            {
                PropertyInfo property 
= targetObj.GetType().GetProperty(item.Name);
                
try
                {
                    property.SetValue(targetObj, item.GetValue(originObj, 
null), null);
                }
                
catch
                {
                    
continue;
                }
            }
        }

 

Spring.net用ObjectWrapper实现赋值代码如下:

Spring.net
        /// <summary>
        
/// 把原始对象的值赋值给目标对象
        
/// </summary>
        
/// <param name="originObj">原始对象</param>
        
/// <param name="targetObj">目标对象</param>
        public static void Fill<O,T>(object originObj, object targetObj)
        {
            ObjectWrapper ow 
= new ObjectWrapper(originObj);
            ObjectWrapper tw 
= new ObjectWrapper(targetObj);
            PropertyInfo[] properties 
= ow.GetPropertyInfos();

            
foreach (PropertyInfo item in properties)
            {
                
try
                {
                    tw.SetPropertyValue(item.Name, ow.GetPropertyValue(item.Name));
                }
                
catch
                {
                    
continue;
                }
            }
        }

 

用FastReflectionLib实现赋值代码如下:

FastReflectionLib
        /// <summary>
        
/// 把原始对象的值赋值给目标对象
        
/// </summary>
        
/// <param name="originObj"></param>
        
/// <param name="targetObj"></param>
        public static void Fill(object originObj, object targetObj)
        {
            PropertyInfo[] properties 
= originObj.GetType().GetProperties();

            
foreach (PropertyInfo item in properties)
            {
                PropertyInfo property 
= targetObj.GetType().GetProperty(item.Name);
                
try
                {
                    property.FastSetValue(targetObj, item.FastGetValue(originObj));
                }
                
catch
                {
                    
continue;
                }
            }
        }

 

为了让任意对象更加真实性,我的两个对象将继承一个类,并且对象中还包括其他对象,对象具体内容就不展现出来了,最下面提供源代

码下载,感兴趣的可以下载试试,如果有什么好的建议,不忘了告诉我一下。

测试代码如下: 

测试代码
        static void Main(string[] args)
        {
            var origin 
= new SourceObject() { Id = 2, Name = "lawson", Url = "http://lawson.cnblogs.com", CreateTime = new DateTime(20001010), baseStr = "1base", otherO = new OtherObj() { others="other object others"} };
            var target 
= new TargetObject() { Id = 3, Name = "aa", Url = "http://www.cnblogs.com", CreateTime = new DateTime(2010101) };

            
int time = 10000;


            Stopwatch stopwatch4 
= Stopwatch.StartNew();
            
for (int i = 0; i < time; i++)
            {
                target.Id 
= origin.Id;
                target.Name 
= origin.Name;
                target.Url 
= origin.Url;
                target.CreateTime 
= origin.CreateTime;
            }
            Console.WriteLine(
string.Format("直接赋值耗时:{0} 毫秒", stopwatch4.ElapsedMilliseconds));


            Stopwatch stopwatch2 
= Stopwatch.StartNew();
            
for (int i = 0; i < time; i++)
            {
                DirectReflect.Exchanger.Fill(origin, target);
            }
            Console.WriteLine(
string.Format("直接反射赋值耗时:{0} 毫秒", stopwatch2.ElapsedMilliseconds));

            Stopwatch stopwatch 
= Stopwatch.StartNew();
            
for (int i = 0; i < time; i++)
            {
                SpringNet.Exchanger.Fill
<SourceObject, TargetObject>(origin, target);
            }
            Console.WriteLine(
string.Format("Springnet赋值耗时:{0} 毫秒", stopwatch.ElapsedMilliseconds));
                        
            Stopwatch stopwatch3 
= Stopwatch.StartNew();
            
for (int i = 0; i < time; i++)
            {
                FastReflect.Exchanger.Fill(origin, target);
            }
            Console.WriteLine(
string.Format("FastReflect赋值耗时:{0} 毫秒", stopwatch3.ElapsedMilliseconds));

            Console.ReadKey();

        }

 

 

在Release编译运行下的结果如下:

直接赋值耗时:0 毫秒
直接反射赋值耗时:187 毫秒
Springnet赋值耗时:3642 毫秒
FastReflect赋值耗时:133 毫秒

在我的测试中,Springnet的ObjectWrapper和直接反射或者FastReflect比较中,性能完全不是一个数量级的。

下面提供我的测试代码下载

 /Files/Lawson/ExchangeValue-lawson.rar

posted @ 2010-12-25 19:39  Lawson  阅读(916)  评论(0编辑  收藏  举报