zoukankan      html  css  js  c++  java
  • 任意两个对象赋值,用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

  • 相关阅读:
    关于匹配的一些问题
    Codeforces Round #396 (Div. 2) A,B,C,D,E
    Codeforces Round #394 (Div. 2) A,B,C,D,E
    HDU 1848 SG函数博弈
    HDU 1536 S-Nim SG博弈
    HDU 2509 Be the Winner nim博弈变形
    HDU 1907 John nim博弈变形
    Codeforces Round #222 (Div. 1) D. Developing Game 线段树有效区间合并
    BZOJ 1031: [JSOI2007]字符加密Cipher 后缀数组
    HDU 5769 Substring 后缀数组
  • 原文地址:https://www.cnblogs.com/Lawson/p/1916866.html
Copyright © 2011-2022 走看看