深拷貝1兼容多構造函數

        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)));
                        }
                    }
                }
            }
        }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章