















还有几天2008就过去了,在这提前祝大家在2009年一切顺利,财源滚滚!
在NET中,拷贝分为浅拷贝和深拷贝,
浅拷贝:创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象(引用MSDN),对于这种的实现其实很简单,就是用Object类的MemberwiseClone方法。
深拷贝:创建一个新对象,这个新对象所包含的值和引用这些都是新的对象,也就是对该对象的所有东西进行完整的复制。MS对于这种方式基本上没有提供出实现,或者说根本就提供不了,因为这有很多因素来制约。不过它还是对少数的几个类提供了,例如DataTable的Copy方法....
"山寨文化",现在已经成为了流行的一个词,"山寨手机"、"山寨版明星"、连"春晚"也要山寨起来了.....!
既然现实环境有那么多的"山寨",那在程序的环境中,我们就更需要了!程序世界中的山寨就是对象的副本!MS只给了我们表层的复制,下面就让我们将"山寨"进行到底!
当我们要用到复制、粘贴、或撤消... 这些动作的时候,往往需要用到对象的副本进行操作,这样就需要去做深拷贝(WindowsForm开发中,这种情况是特别多的),但是麻烦的问题就出现在这里:我们可以实现ICloneable接口,然后手写Clone方法来达到我们的目的,可是,如果对象之间的关系比较多,对象中的属性又比较多的时候,那么对每个类写Clone这个方法的时候... 恐怖呀!这需要增加很多的开发时间,我们为什么不弄一个比较公用的方法呢?!
好的,方法出来了,其实就是做一个基类,里面有个共有的拷贝方法,每个想去深拷贝的类都要继承它。
再看下面BaseCopyObject的代码:
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;namespace CloneProject
{
public abstract class BaseCopyObject
{
#region ICloneable 成员/// <summary>
/// 拷贝对象
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public virtual object CopyObject(params object[] obj)
{
object newObj = null;
Type mType
= this.GetType();Type mFieldType
= field.FieldType; field.SetValue(newObj, pValue);
}
}
基本思路:
1、先获取这个类型的Type,然后利用Activator.CreateInstance获取构造函数。
注意的地方:
因为对于继承BaseCopyObject的类,这些类的构造函数是否公开(Public),参数怎么定义对于这个方法来说是不确定的,所以在该方法对于构造函数做了两个动作
1、对于没有定义Public构造函数的类是复制不了的
2、this.GetConstructParams(),它是用来获取构造函数的参数数组的,子类可以根据自己的需要去定义构造函数接受的参数,默认是为Null的。
2、获取该类型的所有字段,mType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | dBindingFlags.Instance),然后通过FieldInfo的GetValue来获取值,SetValue来赋值,
注意的地方:
1、对于事件字段是不进行复制的,并且复制的时候会把它设置为null,因为对于事件来说,它的范围比较大,不可能对和它有关的对象都进行复制。
2、如果字段是值类型,很简单,直接GetValue和SetValue就可以了,不过对于引用类型有以下三种情况:
A、引用类型继承了BaseCopyObject,可以使用BaseCopyObject的CopyObject方法
pValue = ((BaseCopyObject)pValue).CopyObject(new object[] { this, newObj });
B、A类和B类之间是相互依赖关系的时候,例如a.B = b、并且b.A = a,a、b为A类和B类的对象,这种情况下,复制a对象的时候,对a对象中的所有字段进行复制,但是当复制到b对象的时候,会判断b对象中的字段是否有指回a对象的,如果有就不进行复制,而是赋引用,如果没有,就进行复制。
C、引用类型没有继承BaseCopyObject,例如,包含DataTable...这些对象,当对象中有这些引用的时候,这个基类的CopyObject是不能进行完全处理的,这就需要去重写CopyDefineElement这个方法,并且返回true,通过判断这个类中的字段类型来进行自定义的动作,从而达到自定义拷贝的目的。
3、在有些特殊的情况下,我们不想对某些字段的引用对象进行完整拷贝,这个时候我们可以使用重写CopyDefineElement这个方法(和上面2.C中的一样),达到我们自定义的目的
单元测试代码:
Code
写完咯!在2008年中,看到了"山寨"开始成长,期望看到2009年"山寨"的前方到底是什么?!呵呵
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。