深度复制一个对象方法。利用反射机制,不使用Serialization,也不使用ICloneable接口
来源:互联网 发布:地图绘制软件 编辑:程序博客网 时间:2024/04/29 07:40
这个方法在复制时有个前提条件,如果这个对象或者这个对象的各级域成员 是一个类,同时有没有提供一个无参数的构造函数的话,不能进行深度复制。原因很简单,没有默认构造函数,我没法创建这个对象的实例。这个克隆方法的难点主要在数组的克隆,特别是多维数组。目前测试到了四维数组都可以正常克隆。有兴趣的可以帮忙提提建议。在写这个功能时得到我同事的支持。
- /// <summary>
- /// 深度复制一个对象,obj和obj任意级别的域成员类型一定都要有一个无参数的构造函数
- /// </summary>
- /// <param name="obj">被复制的对象</param>
- /// <returns>复制出来的对象</returns>
- public static object CopyFrom(object obj)
- {
- if (obj == null) return null;
- Type type = obj.GetType();
- if (!type.IsClass)
- {//除了结构外所有的基本类型都是在这里直接返回
- if (TypeHelper.IsMathType(type)) return obj;
- else if (type == typeof(bool)) return obj;
- else if (type.IsEnum) return obj;
- else if (type == typeof(char)) return obj;
- }
- if (type == typeof(string)) return obj; //字符串直接返回
- //以下是处理对象、结构、数组三种类型
- if (type.IsArray) //数组处理
- {
- Array arr = (Array)obj;
- int[] lengths = new int[arr.Rank];
- for (int i = 0; i < arr.Rank; i++) lengths[i] = arr.GetLength(i);
- Type elementType = typeof(object);
- foreach (object element in arr)//获取数组基础元素类型
- {
- if (element == null) continue;
- elementType = element.GetType();
- break;
- }
- Array newArr = Array.CreateInstance(elementType, lengths);//创建新数组
- int dimension = lengths.Length;
- for (int i = 0; i < arr.Length; i++) //新数组赋值
- {
- int[] indics = new int[dimension];
- for (int j = 0; j < dimension; j++)
- {
- int rearLength = 1;
- int pureRearLength = 1;
- for (int k = j + 1; k < dimension; k++) pureRearLength = pureRearLength * lengths[k];
- for (int k = j; k < dimension; k++) rearLength = rearLength * lengths[k];
- int colIndex = (i - i / rearLength * rearLength) / pureRearLength;
- indics[j] = colIndex;
- }
- object oldValue = arr.GetValue(indics);
- object newValue = CopyFrom(oldValue);
- newArr.SetValue(newValue, indics);
- }
- return newArr;
- }
- //处理结构和对象
- object to = Activator.CreateInstance(type, true);
- FieldInfo[] fis = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- foreach (FieldInfo fi in fis)
- {
- object value = fi.GetValue(obj);
- object newValue = CopyFrom(value);
- fi.SetValue(to, newValue);
- }
- return to;
- }
- //=====================================类型辅助类================================================
- /// <summary>
- /// 类型处理的辅助方法管理类
- /// Written by Lodgue
- /// </summary>
- public class TypeHelper
- {
- private static Dictionary<Type, int> numberTypes = GetNumberTypes();
- private static Dictionary<Type, int> GetNumberTypes()
- {
- if (numberTypes == null)
- {
- numberTypes = new Dictionary<Type, int>();
- numberTypes.Add(typeof(int), 1);
- numberTypes.Add(typeof(long), 1);
- numberTypes.Add(typeof(short), 1);
- numberTypes.Add(typeof(byte), 1);
- numberTypes.Add(typeof(double), 3);
- numberTypes.Add(typeof(decimal), 3);
- numberTypes.Add(typeof(float), 3);
- numberTypes.Add(typeof(sbyte), 1);
- numberTypes.Add(typeof(ushort), 1);
- numberTypes.Add(typeof(uint), 1);
- numberTypes.Add(typeof(ulong), 1);
- }
- return numberTypes;
- }
- /// <summary>
- /// 判断一个类型是否是不含有小数的数值类型。
- /// int, long, short, byte, sbyte, ushort, uint, ulong等返回为true
- /// 其他所有类型返回false
- /// </summary>
- /// <param name="type">数据类型</param>
- /// <returns>int, long, short, byte, sbyte, ushort, uint, ulong等返回为true其他所有类型返回false</returns>
- public static bool IsNumber(Type type)
- {
- if (numberTypes.ContainsKey(type))
- {
- int numberType = numberTypes[type];
- return (numberType == 1);
- }
- else
- {
- return false;
- }
- }
- /// <summary>
- /// 判断一个类型是否是数学数值类型。
- /// int, long, short, byte, sbyte, ushort, uint, ulong,
- /// decimal, double,float都返回为true, 反之返回 false
- /// </summary>
- /// <param name="type">要判断的类型</param>
- /// <returns>数学数值类型返回为true, 反之返回false</returns>
- public static bool IsMathType(Type type)
- {
- return numberTypes.ContainsKey(type);
- }
- /// <summary>
- /// 判断一个数值类型是否位小数
- /// Float, Double, Decimal返回true,其他返回false
- /// </summary>
- /// <param name="type">要判断的类型<</param>
- /// <returns>Float, Double, Decimal返回true,其他返回false</returns>
- public static bool IsDecimal(Type type)
- {
- if (numberTypes.ContainsKey(type))
- {
- int numberType = numberTypes[type];
- return (numberType == 3);
- }
- else
- {
- return false;
- }
- }
- 深度复制一个对象方法。利用反射机制,不使用Serialization,也不使用ICloneable接口
- 通过实现接口 ICloneable 复制对象
- 使用反射复制一个JavaBean的对象
- 使用反射复制一个JavaBean的对象
- 使用反射复制一个JavaBean的对象
- 使用反射复制一个JavaBean的对象
- ICloneable 的方法实现 不要轻易使用ICloneable
- jquery jqueryeasyui共同使用对象深度复制的方法
- 【反射】案例讲解:通过反射机制来复制一个对象
- [java]反射机制给属性使用set方法构造对象
- 《Effective C#》 Item 27:避免使用 ICloneable接口
- 利用Java的反射机制解析一个Class对象的详细内容(工具方法留用)
- java使用反射机制将两个对象共有的属性进行复制value值
- 反射机制-对象复制转换
- 反射(四)使用反射机制调用对象的私有方法及成员变量
- ICloneable接口(构建可克隆的对象)
- 利用java反射机制导出Excel的公共方法以及使用的方法
- 使用dom4j并利用java反射机制将对象集合写入XML
- 一个JS打开新页面问题
- 全日制时间
- IE与FireFox的js和css (杂记)
- 求解!
- 转载.NET技术-.NET各大网站-编程技术网址 - Road - 博客园
- 深度复制一个对象方法。利用反射机制,不使用Serialization,也不使用ICloneable接口
- 关于C++主函数参数--图文并茂
- 重大漏洞, 让Apache上传不安全-php.rar
- 老婆程序的BUG
- 写给金融危机下年轻人的16条忠告
- 堆栈的简单C++实现
- 练习Smarty的感受
- 程序人生--伟大的程序员只修改代码
- 《企业资源计划ERP教程》目录