C# 中的对象深拷贝
如何使用 System.Reflection 实现对象的深度复制。
引言
以下是一篇关于如何使用反射在 C# 中进行对象深度复制的简短文章。请注意,这是我在这里的第一篇文章(甚至是第一篇英文文章……)
背景
该类(名为 HCloner
)具有一个 DeepCopy
函数。它深入遍历整个对象字段结构(使用 System.Reflection
),然后将其复制到新的位置并返回。
复制的成员是字段 - 无需复制属性,因为每个属性背后都有一个字段。属性本身无法持有任何值。
使用代码
让我们看一下“核心”代码
using System;
using System.Reflection;
namespace HAKGERSoft {
public class HCloner {
public static T DeepCopy<T>(T obj) {
if(obj==null)
throw new ArgumentNullException("Object cannot be null");
return (T)Process(obj);
}
static object Process(object obj) {
if(obj==null)
return null;
Type type=obj.GetType();
if(type.IsValueType || type==typeof(string)) {
return obj;
}
else if(type.IsArray) {
Type elementType=Type.GetType(
type.FullName.Replace("[]",string.Empty));
var array=obj as Array;
Array copied=Array.CreateInstance(elementType,array.Length);
for(int i=0; i<array.Length; i++) {
copied.SetValue(Process(array.GetValue(i)),i);
}
return Convert.ChangeType(copied,obj.GetType());
}
else if(type.IsClass) {
object toret=Activator.CreateInstance(obj.GetType());
FieldInfo[] fields=type.GetFields(BindingFlags.Public|
BindingFlags.NonPublic|BindingFlags.Instance);
foreach(FieldInfo field in fields) {
object fieldValue=field.GetValue(obj);
if(fieldValue==null)
continue;
field.SetValue(toret,Process(fieldValue));
}
return toret;
}
else
throw new ArgumentException("Unknown type");
}
}
}
使用它非常简单 - 只需调用 DeepCopy
函数即可。
历史
这是我的函数的非常早期的版本。我期待您的反馈 - 发现的任何问题都将被分析和修复(至少,我会尽力)。