C#自定义DeepCopy

一个DeepCopyParameterHelper类,帮助深拷贝各种类型的对象(如果有BUG,欢迎留言讨论)

public class DeepCopyParameterHelper
    {

        private DeepCopyParameterHelper() { }
        /// <summary>
        /// Deep copy, implemented by serialization and deserialization
        /// </summary>
        /// <typeparam name="T">The class type of the deep copy</typeparam>
        /// <param name="obj">Deep copy class objects</param>
        /// <returns></returns>
        public static T DeepCopyByBin<T>(T obj)
        {
            if (obj == null)
                return default(T);
            //If it is a string or value type, it is returned directly
            if (obj is string || obj.GetType().IsValueType) return obj;
            object retval;
            using (MemoryStream ms = new MemoryStream())
            {
                BinaryFormatter bf = new BinaryFormatter();
                //Serialize to stream
                bf.Serialize(ms, obj);
                ms.Seek(0, SeekOrigin.Begin);
                //Deserialize to an object
                retval = bf.Deserialize(ms);
                ms.Close();
            }
            return (T)retval;
        }

        /// <summary>
        /// Deep copy, implemented by reflection
        /// </summary>
        /// <typeparam name="T">The class type of the deep copy</typeparam>
        /// <param name="obj">Deep copy class objects</param>
        /// <returns></returns>
        public static T DeepCopyByReflect<T>(T obj)
        {
            try
            {
                if (obj == null)
                    return default(T);
                //If it is a string or value type or is null, it is returned directly
                if (obj is string || obj is int || obj.GetType().IsValueType) return obj;
                var type = obj.GetType();
                if (type.Name.ToLower().Contains("int") || type.Name == "Entry[]")
                    return obj;
                object retval = Activator.CreateInstance(type);
                FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
                foreach (FieldInfo field in fields)
                {
                    try
                    {
                        if (field.FieldType.Name.Equals("List`1"))
                        {
                            var t1 = field.FieldType.GenericTypeArguments[0];
                            MethodInfo mi = typeof(DeepCopyParameterHelper).GetMethod("DeepCopyList")?.MakeGenericMethod(new Type[] { t1 });
                            if (mi != null)
                            {
                                var result = mi.Invoke(typeof(DeepCopyParameterHelper), new[] { field.GetValue(obj) });
                                field.SetValue(retval, result);
                            }
                        }
                        else if (field.FieldType.Name.Equals("Dictionary`2"))
                        {
                            var t1 = field.FieldType.BaseType;
                            MethodInfo mi = typeof(DeepCopyParameterHelper).GetMethod("DeepCopyDictionary")?.MakeGenericMethod(new Type[] { t1 });
                            if (mi != null)
                            {
                                var result = mi.Invoke(typeof(DeepCopyParameterHelper), new[] { field.GetValue(obj) });
                                field.SetValue(retval, result);
                            }
                        }
                        else
                        {
                            field.SetValue(retval, DeepCopyByReflect(field.GetValue(obj)));
                        }
                    }
                    catch (Exception)
                    {
                        // ignored
                    }
                }
                return (T)retval;
            }
            catch (Exception ex)
            {
                
                return default;
            }
        }

        /// <summary>
        /// Clones the specified list.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list">The list.</param>
        /// <returns>List{``0}.</returns>
        public static List<T> DeepCopyList<T>(object list)
        {
            List<T> result = new List<T>();
            if (list != null)
            {
                foreach (var item in ((List<T>) list))
                {
                    var type = item.GetType();
                    if (type.Name.Equals("Dictionary`2") || type.Name.Equals("KeyCollection"))
                    {
                        result.Add((T)DeepCopyDictionary(item));
                    }
                    else
                    {
                        result.Add(DeepCopyByReflect(item));
                    }
                }
            }
            return result;
        }

        public static object DeepCopyDictionary(object obj)
        {
            IDictionary srcDictionary = obj as IDictionary;
            if (srcDictionary != null && srcDictionary.Count > 0)
            {
                // Create new map instance
                IDictionary dstDictionary = Activator.CreateInstance(srcDictionary.GetType()) as IDictionary;
                // deep copy each object in map
                foreach (object o in srcDictionary.Keys)
                {
                    if (dstDictionary != null) dstDictionary[o] = srcDictionary[o];
                }
                return dstDictionary;
            }
            return srcDictionary;
        }
    }

雷区:
有些类把构造函数初始化加参数了,就会在以下这个地方抛异常,就会返回null,望周知

object retval = Activator.CreateInstance(type);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值