public static T DeepCloneObject<T>(T obj) where T : class { //System.String類型似乎比較特殊,複製它的所有字段,並不能複製它本身 //不過由於System.String的不可變性,即使指向同一對象,也無所謂 //而且.NET裏本來就用字符串池來維持 if (obj == null || obj.GetType() == typeof(string)) return obj; object newObj = null; try { //嘗試調用默認構造函數 newObj = Activator.CreateInstance(obj.GetType()); } catch { //失敗的話,只好枚舉構造函數了 foreach (ConstructorInfo ci in obj.GetType().GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { try { ParameterInfo[] pis = ci.GetParameters(); object[] objs = new object[pis.Length]; for (int i = 0; i < pis.Length; i++) { if (pis[i].ParameterType.IsValueType) objs[i] = Activator.CreateInstance(pis[i].ParameterType); else //參數類型可能是抽象類或接口,難以實例化 //我能想到的就是枚舉應用程序域裏的程序集,找到實現了該抽象類或接口的類 //但顯然過於複雜了 objs[i] = null; } newObj = ci.Invoke(objs); //無論調用哪個構造函數,只要成功就行了 break; } catch { } } } foreach (FieldInfo fi in obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { if (fi.FieldType.IsValueType || fi.FieldType == typeof(string)) fi.SetValue(newObj, fi.GetValue(obj)); else fi.SetValue(newObj, DeepCloneObject(fi.GetValue(obj))); } //基類的私有實例字段在子類裏檢索不到,但它仍佔據子類對象的內存空間 Deep(newObj, obj); return (T)newObj; } //克隆繼承樹上的私有實例字段 public static void Deep(object newObj, object obj) { for (Type father = newObj.GetType().BaseType; father != typeof(object); father = father.BaseType) { foreach (FieldInfo fi in father.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)) { //只需要處理私有字段,因爲非私有成員已經在子類處理過了 if (fi.IsPrivate) { if (fi.FieldType.IsValueType || fi.FieldType == typeof(string)) { fi.SetValue(newObj, fi.GetValue(obj)); } else { fi.SetValue(newObj, DeepCloneObject(fi.GetValue(obj))); } } } } }