一个克隆对象的C#基类
2008-04-24 11:35
351 查看
ICloneable接口的类。应用于:C#,.NET
简介
虽然在现实世界中的克隆课题是有争议的,在.NET世界使用它却足够安全,难道不是吗?为实现一个类你究竟有多少次要实现ICloneable接口,而且每一次都写相同的代码,或为每个类写特定的代码。而且,当你的类加入一个新的字段时,往往会忘记更新这个新字段的克隆方法。如果我没说错的话,这种时候往往会带来恼人的bugs。这是我的类得以存在的原因。藉由反射机制的小小帮助,我建立了一个用缺省行为实现了ICloneable接口的抽象类。现在或许你正在问自己:什么是缺省行为?那么我很高兴你这样询问。克隆的缺省行为,是采用以下的规则来克隆类中的每一个字段:查看一下类中的每一个字段是否支持ICloneable接口如果某字段不支持
ICloneable
接口
,
那么该字段将以常规方式处理。这意味着,如果该字段是一个值类型,那么该值被拷贝;如果该字段是一个引用类型,克隆的字段将指向同一个对象。如果该字段支持
ICloneable
接口
,
我们将使用其本身的
Clone
方法对其进行克隆。如果该字段支持
IEnumerable
接口
,
我们需要检查他是否支持IList或IDictionary接口
。如果支持,那么我们迭代该集件,并且查看集合的每一项是否支持
ICloneable接口。
如何使用
让你的类支持
Icloneable
接口所要做的就是
,
将你的类继承自如下所述的
BaseObject
类
:
publicclassMyClass:BaseObject
{
publicstringmyStr=”test”;
publicintid;
}
publicclassMyContainer:BaseObject
{
publicstringname=“test2”;
publicMyClass[]myArray=newMyClass[5];
publicclassMyContainer()
{
for(inti=0;i<5;i++)
{
this.myArray[I]=newMyClass();
}
}}
现在在Main方法中加入如下代码:
staticvoidMain(string[]args)
{
MyContainercon1=newMyContainer();
MyContainercon2=(MyContainer)con1.Clone();
con2.myArray[0].id=5;
}
当监测
con2
实例时,你将会看到
MyClass
实例的第一项已经变为5,而
con1
实例却没有改变。这样你将明白加入到类中的任意支持
ICloneable接口的
字段将被同样地克隆。而且,如果该字段支持IList或IDictionary接口,克隆方法将侦测该字段,轮询所有项,并同样地试图对他们进行克隆
。
实现
///<summary>
///BaseObject类是一个用来继承的抽象类。
///每一个由此类继承而来的类将自动支持克隆方法。
///该类实现了Icloneable接口,并且每个从该对象继承而来的对象都将同样地
///支持Icloneable接口。///</summary>[/code]
publicabstractclassBaseObject:ICloneable
{
///<summary>
///克隆对象,并返回一个已克隆对象的引用
///</summary>
///<returns>引用新的克隆对象</returns>publicobjectClone()[/code]
{
//首先我们建立指定类型的一个实例[/code]objectnewObject=Activator.CreateInstance(this.GetType());
//我们取得新的类型实例的字段数组。[/code]FieldInfo[]fields=newObject.GetType().GetFields();
inti=0;
foreach(FieldInfofiinthis.GetType().GetFields())
{
//我们判断字段是否支持ICloneable接口。TypeICloneType=fi.FieldType.[/code]
GetInterface("ICloneable",true);
if(ICloneType!=null)
{
//取得对象的Icloneable接口。[/code]ICloneableIClone=(ICloneable)fi.GetValue(this);
//我们使用克隆方法给字段设定新值。
fields[i].SetValue(newObject,IClone.Clone());
}
else
{
//如果该字段部支持Icloneable接口,直接设置即可。[/code]fields[i].SetValue(newObject,fi.GetValue(this));
}
//现在我们检查该对象是否支持IEnumerable接口,如果支持,
//我们还需要枚举其所有项并检查他们是否支持IList或IDictionary接口。
TypeIEnumerableType=fi.FieldType.GetInterface
("IEnumerable",true);
if(IEnumerableType!=null)
{
//取得该字段的IEnumerable接口
IEnumerableIEnum=(IEnumerable)fi.GetValue(this);
//这个版本支持IList或IDictionary接口来迭代集合。[/code]
TypeIListType=fields[i].FieldType.GetInterface
("IList",true);
TypeIDicType=fields[i].FieldType.GetInterface
("IDictionary",true);
intj=0;
if(IListType!=null)
{
相关文章推荐
- 一个克隆对象的C#基类
- C#中如何深度克隆一个对象?
- C# 克隆一个对象(实例)
- 【转】C#怎么遍历一个对象里面的全部属性?
- c# 将datatable的每一行转换为一个对象
- MVC5中Model层开发数据注解 EF Code First Migrations数据库迁移 C# 常用对象的的修饰符 C# 静态构造函数 MSSQL2005数据库自动备份问题(到同一个局域网上的另一台电脑上) MVC 的HTTP请求
- 工厂模式:封装对象的创建(一、在基类中定义一个静态成员函数)
- 克隆一个对象——原型模式深入解析
- c# 中基类变量指向派生类对象的实例化
- C#中通过一个对象,得到属性(字符串形式)的值
- C#中的深复制和浅复制(在C#中克隆对象)
- 在C#如何遍历一个对象的所有属性
- C# 引用对象深克隆帮助类
- 使用反射将一个对象的值复制给另一个对象(同一个对象或者基于同一个基类)
- C# 对象克隆
- C# 通过反射为一个对象赋值
- c# 把一个匿名对象赋值给一个Object类型的变量后,怎么取这个变量? c# dynamic动态类型和匿名类 详解C# 匿名对象(匿名类型)、var、动态类型 dynamic 深入浅析C#中的var和dynamic
- C# String.Format的格式限定符与Format方法将多个对象格式化一个字符串原理
- c# 对象克隆
- C#语法基础-定义一个矩形对象