C#开发笔记之17-如何用C#深克隆一个对象(传统方案)?

C#开发笔记之17-如何用C#深克隆一个对象(传统方案)?

C#开发笔记概述

另外可参考文章:C#开发笔记之20-如何用C#深克隆一个对象(优雅方案)?

文章目录

概述

本文介绍如何使用C#的反射实现传统的深克隆解决方案?

解释

public static class CloneHelper {

    public static object Clone(object obj) {
        var type = obj.GetType();
        var properties = type.GetProperties();

        var result = type.InvokeMember("", BindingFlags.CreateInstance, null, obj, null);

        foreach (var pi in properties) {
            if (pi.CanWrite) {
                var value = pi.GetValue(obj, null);
                pi.SetValue(result, value, null);
            }
        }

        return result;
    }

    /// <summary>
    /// 对象Clone
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="t"></param>
    /// <returns></returns>
    public static T DeepCloneObject<T>(this T t) where T : class {
        var instance = Activator.CreateInstance<T>();
        var propertyInfos = instance.GetType().GetProperties();

        foreach (var propertyInfo in propertyInfos) {
            if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) {
                var nullableConverter = new NullableConverter(propertyInfo.PropertyType);

                try {
                    propertyInfo.SetValue(instance, Convert.ChangeType(propertyInfo.GetValue(t), nullableConverter.UnderlyingType), null);
                }
                catch (Exception ex) {
                    var typeArray = propertyInfo.PropertyType.GetGenericArguments();
                    propertyInfo.SetValue(instance, Convert.ChangeType(propertyInfo.GetValue(t), typeArray[0]), null);
                }
            }
            else {
                propertyInfo.SetValue(instance, Convert.ChangeType(propertyInfo.GetValue(t), propertyInfo.PropertyType), null);
            }
        }

        return instance;
    }

    /// <summary>
    /// List的Clone
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="tList"></param>
    /// <returns></returns>
    public static IList<T> DeepCloneList<T>(this IList<T> tList) where T : class {
        var result = new List<T>();

        foreach (var item in tList) {
            var model = Activator.CreateInstance<T>();
            var propertyInfos = model.GetType().GetProperties();

            foreach (var propertyInfo in propertyInfos) {
                if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) {
                    var nullableConverter = new NullableConverter(propertyInfo.PropertyType);
                    propertyInfo.SetValue(model, Convert.ChangeType(propertyInfo.GetValue(item), nullableConverter.UnderlyingType), null);
                }
                else {
                    propertyInfo.SetValue(model, Convert.ChangeType(propertyInfo.GetValue(item), propertyInfo.PropertyType), null);
                }
            }

            result.Add(model);
        }

        return result;
    }

}

本文由 .Net中文网 原创发布,欢迎大家踊跃转载。

转载请注明本文地址:https://www.byteflying.com/archives/3435

发表评论

登录后才能评论