对象的深克隆-Clone【利用反射】转:http://www.codeproject.com/csharp/cloneimpl_class.asp
2007-10-30 19:35
801 查看
<PRE lang=cs id=pre2 style="MARGIN-TOP: 0px">/// <summary>
/// <B>BaseObject</B> class is an abstract class for you to derive from.
/// Every class that will be dirived from this class will support the
/// <B>Clone</B> method automaticly.
/// The class implements the interface <I>ICloneable</I> and there
/// for every object that will be derived
/// from this object will support the <I>ICloneable</I> interface as well.
/// </summary>
public abstract class BaseObject : ICloneable
{
/// <summary>
/// Clone the object, and returning a reference to a cloned object.
/// </summary>
/// <returns>Reference to the new cloned
/// object.</returns>
public object Clone()
{
//First we create an instance of this specific type.
object newObject = Activator.CreateInstance( this.GetType() );
//We get the array of fields for the new type instance.
FieldInfo[] fields = newObject.GetType().GetFields();
int i = 0;
foreach( FieldInfo fi in this.GetType().GetFields() )
{
//We query if the fiels support the ICloneable interface.
Type ICloneType = fi.FieldType.
GetInterface( "ICloneable" , true );
if( ICloneType != null )
{
//Getting the ICloneable interface from the object.
ICloneable IClone = (ICloneable)fi.GetValue(this);
//We use the clone method to set the new value to the field.
fields[i].SetValue( newObject , IClone.Clone() );
}
else
{
// If the field doesn't support the ICloneable
// interface then just set it.
fields[i].SetValue( newObject , fi.GetValue(this) );
}
//Now we check if the object support the
//IEnumerable interface, so if it does
//we need to enumerate all its items and check if
//they support the ICloneable interface.
Type IEnumerableType = fi.FieldType.GetInterface
( "IEnumerable" , true );
if( IEnumerableType != null )
{
//Get the IEnumerable interface from the field.
IEnumerable IEnum = (IEnumerable)fi.GetValue(this);
//This version support the IList and the
//IDictionary interfaces to iterate on collections.
Type IListType = fields[i].FieldType.GetInterface
( "IList" , true );
Type IDicType = fields[i].FieldType.GetInterface
( "IDictionary" , true );
int j = 0;
if( IListType != null )
{
//Getting the IList interface.
IList list = (IList)fields[i].GetValue(newObject);
foreach( object obj in IEnum )
{
//Checking to see if the current item
//support the ICloneable interface.
ICloneType = obj.GetType().
GetInterface( "ICloneable" , true );
if( ICloneType != null )
{
//If it does support the ICloneable interface,
//we use it to set the clone of
//the object in the list.
ICloneable clone = (ICloneable)obj;
list[j] = clone.Clone();
}
//NOTE: If the item in the list is not
//support the ICloneable interface then in the
//cloned list this item will be the same
//item as in the original list
//(as long as this type is a reference type).
j++;
}
}
else if( IDicType != null )
{
//Getting the dictionary interface.
IDictionary dic = (IDictionary)fields[i].
GetValue(newObject);
j = 0;
foreach( DictionaryEntry de in IEnum )
{
//Checking to see if the item
//support the ICloneable interface.
ICloneType = de.Value.GetType().
GetInterface( "ICloneable" , true );
if( ICloneType != null )
{
ICloneable clone = (ICloneable)de.Value;
dic[de.Key] = clone.Clone();
}
j++;
}
}
}
i++;
}
return newObject;
}
}
</PRE>
/// <B>BaseObject</B> class is an abstract class for you to derive from.
/// Every class that will be dirived from this class will support the
/// <B>Clone</B> method automaticly.
/// The class implements the interface <I>ICloneable</I> and there
/// for every object that will be derived
/// from this object will support the <I>ICloneable</I> interface as well.
/// </summary>
public abstract class BaseObject : ICloneable
{
/// <summary>
/// Clone the object, and returning a reference to a cloned object.
/// </summary>
/// <returns>Reference to the new cloned
/// object.</returns>
public object Clone()
{
//First we create an instance of this specific type.
object newObject = Activator.CreateInstance( this.GetType() );
//We get the array of fields for the new type instance.
FieldInfo[] fields = newObject.GetType().GetFields();
int i = 0;
foreach( FieldInfo fi in this.GetType().GetFields() )
{
//We query if the fiels support the ICloneable interface.
Type ICloneType = fi.FieldType.
GetInterface( "ICloneable" , true );
if( ICloneType != null )
{
//Getting the ICloneable interface from the object.
ICloneable IClone = (ICloneable)fi.GetValue(this);
//We use the clone method to set the new value to the field.
fields[i].SetValue( newObject , IClone.Clone() );
}
else
{
// If the field doesn't support the ICloneable
// interface then just set it.
fields[i].SetValue( newObject , fi.GetValue(this) );
}
//Now we check if the object support the
//IEnumerable interface, so if it does
//we need to enumerate all its items and check if
//they support the ICloneable interface.
Type IEnumerableType = fi.FieldType.GetInterface
( "IEnumerable" , true );
if( IEnumerableType != null )
{
//Get the IEnumerable interface from the field.
IEnumerable IEnum = (IEnumerable)fi.GetValue(this);
//This version support the IList and the
//IDictionary interfaces to iterate on collections.
Type IListType = fields[i].FieldType.GetInterface
( "IList" , true );
Type IDicType = fields[i].FieldType.GetInterface
( "IDictionary" , true );
int j = 0;
if( IListType != null )
{
//Getting the IList interface.
IList list = (IList)fields[i].GetValue(newObject);
foreach( object obj in IEnum )
{
//Checking to see if the current item
//support the ICloneable interface.
ICloneType = obj.GetType().
GetInterface( "ICloneable" , true );
if( ICloneType != null )
{
//If it does support the ICloneable interface,
//we use it to set the clone of
//the object in the list.
ICloneable clone = (ICloneable)obj;
list[j] = clone.Clone();
}
//NOTE: If the item in the list is not
//support the ICloneable interface then in the
//cloned list this item will be the same
//item as in the original list
//(as long as this type is a reference type).
j++;
}
}
else if( IDicType != null )
{
//Getting the dictionary interface.
IDictionary dic = (IDictionary)fields[i].
GetValue(newObject);
j = 0;
foreach( DictionaryEntry de in IEnum )
{
//Checking to see if the item
//support the ICloneable interface.
ICloneType = de.Value.GetType().
GetInterface( "ICloneable" , true );
if( ICloneType != null )
{
ICloneable clone = (ICloneable)de.Value;
dic[de.Key] = clone.Clone();
}
j++;
}
}
}
i++;
}
return newObject;
}
}
</PRE>
相关文章推荐
- http://www.codeproject.com/dotnet/WWF.asp#xx1331348xx
- ASP.NET Internals: Viewstate and Page Life Cycle(http://www.codeproject.com/KB/aspnet/aspnetviewstatepagecycle.aspx)
- Exploring Caching in ASP.NET (http://www.codeproject.com/KB/aspnet/ExploringCaching.aspx)
- 和matlab开发应用有关的网址http://www.codeproject.com/dotnet/matlabeng.asp
- 利用webservice和.net技术上传和下载文件--Sending files in chunks with MTOM Web Services and .NET 2.0 from:http://www.codeproject.com/soap/MTO
- ASP.NET Internals: Request Architecture(http://www.codeproject.com/KB/aspnet/aspnetrequestarchitecture.aspx)
- Cache Management in ASP.NET(http://www.codeproject.com/KB/web-cache/cachemanagementinaspnet.aspx)
- Querying Active Directory using .NET classes and LDAP queries(http://www.codeproject.com/dotnet/activedirquery.asp)
- http://www.codeproject.com/dotnet/vbnet_c__difference.asp
- 文件比较 转自http://www.codeproject.com/cpp/vdiff.asp
- http://www.c-sharpcorner.com/WindowsServices.asp
- 抓屏的各种方法(http://www.codeproject.com/KB/dialog/screencap.aspx)
- http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=9332 多broser
- VS高级调试技巧 转自CodeProject (http://www.codeproject.com/KB/debug/Advanced_Debugging.aspx)
- C#之玩转反射【转:http://www.cnblogs.com/yaozhenfa/p/CSharp_Reflection_1.html】
- ListControl參考:http://www.codeproject.com/KB/list/SubItemSel.aspx
- .net 垃圾回收学习[http://www.codeproject.com/KB/dotnet/idisposable.aspx][翻译&&学习][2]
- http://www.codeproject.com 代码营,找学习文档的好去处
- vc曲线库 http://www.codeproject.com/KB/miscctrl/pgllib.aspx
- http://www.codeproject.com/KB/database/Building_Dynamic_SQL.aspx?azid=2