zoukankan      html  css  js  c++  java
  • 对象的深拷贝--反射

    继续上节的对象深拷贝,上节讲了通过序列化和反序列化来实现深度拷贝,这一节我们来讲述一下第二种深度拷贝的方法,反射。通过反射来实现深度拷贝。

    反射主要是在运行时获取对象的元信息,System.Reflection命名空间允许我们在程序运行时来获取对象的信息、创建已存在类的实例,也能够获取对象的属性和执行对象的方法。

    下面我创建一个静态的方法来接收任何类型的对象,并返回一个新对象的引用。

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Reflection;
     6 
     7 namespace ReflectionCopy
     8 {
     9     public class Utility
    10     {
    11         public static object CloneObject(object objsource)
    12         {
    13             //第一步获取原对象的类型,并创建一个同类型的对象
    14             Type typesource = objsource.GetType();
    15 
    16             object objTarget = Activator.CreateInstance(typesource);
    17 
    18             //第二步获取原对象的所有属性
    19 
    20             PropertyInfo[] propertyinfo = typesource.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
    21 
    22             //第三步将原对象的所有属性赋给目标对象
    23 
    24             foreach (PropertyInfo item in propertyinfo)
    25             {
    26                 if (item.CanWrite)
    27                 {
    28 
    29                     //值类型,字符串,枚举类型直接把值复制,不存在浅拷贝  虽然字符串是引用类型,但是字符串是不可变的,每次都是创建新的字符串对象,所以不存在浅拷贝
    30                     if (item.PropertyType.IsEnum || item.PropertyType.IsValueType || item.PropertyType.Equals(typeof(System.String)))
    31                     {
    32 
    33                         item.SetValue(objTarget, item.GetValue(objsource, null), null);
    34                     }
    35                     else
    36                     {
    37                         object objpropertyvalue = item.GetValue(objsource, null);
    38 
    39                         item.SetValue(objTarget, CloneObject(objpropertyvalue), null);
    40                     }
    41                 }
    42             }
    43             return objTarget;
    44         }
    45     }
    46 }

    这个方法也可以做成一个扩展方法:

     1 public static class ObjectExtension
     2 {
     3     public static object CloneObject(this object objSource)
     4     {
     5         //Get the type of source object and create a new instance of that type
     6         Type typeSource = objSource.GetType();
     7         object objTarget = Activator.CreateInstance(typeSource);
     8  
     9         //Get all the properties of source object type
    10         PropertyInfo[] propertyInfo = typeSource.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
    11  
    12         //Assign all source property to taget object 's properties
    13         foreach (PropertyInfo property in propertyInfo)
    14         {
    15             //Check whether property can be written to
    16             if (property.CanWrite)
    17             {
    18                 //check whether property type is value type, enum or string type
    19                 if (property.PropertyType.IsValueType || property.PropertyType.IsEnum || property.PropertyType.Equals(typeof(System.String)))
    20                 {
    21                     property.SetValue(objTarget, property.GetValue(objSource, null), null);
    22                 }
    23                 //else property type is object/complex types, so need to recursively call this method until the end of the tree is reached
    24                 else
    25                 {
    26                     object objPropertyValue = property.GetValue(objSource, null);
    27                     if (objPropertyValue == null)
    28                     {
    29                         property.SetValue(objTarget, null, null);
    30                     }
    31                     else
    32                     {
    33                         property.SetValue(objTarget, objPropertyValue.CloneObject(), null);
    34                     }
    35                 }
    36             }
    37         }
    38         return objTarget;
    39     }
    40 }

    现在我们调用该方法,看看结果:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 
     6 namespace ReflectionCopy
     7 {
     8     class Program
     9     {
    10         static void Main(string[] args)
    11         {
    12             Employee emp = new Employee();
    13 
    14             emp.EmployeeId = 1000;
    15             emp.EmployeeName = "IT少年";
    16             emp.Department = new Department { DepartmentId = 1, DepartmentName = "Examination" };
    17 
    18             Employee empclone = emp.CloneObject() as Employee;
    19 
    20             emp.EmployeeId = 1003;
    21             emp.EmployeeName = "TTT";
    22             emp.Department.DepartmentId = 3;
    23             emp.Department.DepartmentName = "admin";
    24             Console.WriteLine("----emp原始对象------");
    25             Console.WriteLine("拷贝前DepartmentName应该是admin:  " + emp.Department.DepartmentName);
    26             Console.WriteLine("拷贝前DepartmentID应该是3:  " + emp.Department.DepartmentId);
    27 
    28             Console.WriteLine("----empclone拷贝对象------");
    29             Console.WriteLine("拷贝DepartmentName应该是Examination:    " + empclone.Department.DepartmentName);
    30             Console.WriteLine("拷贝DepartmentID应该是1:     " + empclone.Department.DepartmentId);
    31             Console.ReadKey();
    32         }
    33 
    34     }
    35 }

    运行结果可以看出和序列化和反序列化深拷贝一样的。

  • 相关阅读:
    玩转MySQL之Linux下的简单操作(服务启动与关闭、启动与关闭、查看版本)
    玩转MySQL之Linux下修改默认编码
    机器学习算法及应用领域相关的中国大牛
    [转载]Python 包管理工具解惑
    Vim常用操作和快捷键技巧总结
    [转载]那些C++牛人的博客
    [转载]学习c/c++的好网站
    [转载]C++内存管理
    [转载]SQL数据库如何加快查询速度
    [转载]Python3.x和Python2.x的区别
  • 原文地址:https://www.cnblogs.com/yplong/p/5289512.html
Copyright © 2011-2022 走看看