65.9K
CodeProject 正在变化。 阅读更多。
Home

C# 中的对象深拷贝

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (13投票s)

2009年7月18日

CPOL
viewsIcon

157404

downloadIcon

1181

如何使用 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 函数即可。

历史

这是我的函数的非常早期的版本。我期待您的反馈 - 发现的任何问题都将被分析和修复(至少,我会尽力)。

© . All rights reserved.