简体   繁体   English

使用System.Reflection对对象进行深层复制?

[英]Deep copy of objects using System.Reflection?

如何在C#中使用System.Reflection对对象进行深层复制?

One simple way is to use JSON: 一种简单的方法是使用JSON:

public static T DeepClone<T>(T source)
{
    var serialized = JsonConvert.SerializeObject(source);
    return JsonConvert.DeserializeObject<T>(serialized);
}

which does the reflection for you. 为您做反射。 Obviously it won't work with anything that, for example, has a handle to an unmanaged object and so on. 显然,它不适用于任何具有非托管对象句柄的东西,依此类推。

(You can use NuGet to install Newtonsoft.Json into your project.) (您可以使用NuGet将Newtonsoft.Json安装到您的项目中。)

By default Json won't serialise private fields. 默认情况下,Json不会序列化私有字段。

You can fix that like so: 您可以这样解决:

public static T DeepClone<T>(T source)
{
    var settings = new JsonSerializerSettings {ContractResolver = new MyContractResolver()};
    var serialized = JsonConvert.SerializeObject(source, settings);
    return JsonConvert.DeserializeObject<T>(serialized);
}

public class MyContractResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var props = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                        .Select(p => base.CreateProperty(p, memberSerialization))
                    .Union(type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                                .Select(f => base.CreateProperty(f, memberSerialization)))
                    .ToList();
        props.ForEach(p => { p.Writable = true; p.Readable = true; });
        return props;
    }
}

Here's a full sample console app that shows how an arbitrary class with private fields can be cloned. 这是一个完整的示例控制台应用程序,显示了如何克隆具有私有字段的任意类。 Note that Json tries to use a constructor to set the fields and/or properties, and if the constructor parameter names don't match the field or property names it won't work correctly: 请注意, Json尝试使用构造函数来设置字段和/或属性,并且如果构造函数的参数名称与字段或属性名称不匹配,它将无法正常工作:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace ConsoleApplication1
{
    class Test
    {
        public Test(double y, string s, int x)
        {
            this.Y = y;
            this.s = s;
            this.X = x;
        }

        public int X;

        public double Y { get; private set; }

        public string Z         
        {
            get
            {
                return s;
            }
        }

        private string s;
    }

    class Program
    {
        static void Main()
        {
            var test = new Test(1.2345, "12345", 12345);
            test.X = 12345;

            var copy = DeepClone(test);

            Console.WriteLine("X = " + copy.X);
            Console.WriteLine("Y = " + copy.Y);
            Console.WriteLine("Z = " + copy.Z);
        }

        public static T DeepClone<T>(T source)
        {
            var settings = new JsonSerializerSettings {ContractResolver = new MyContractResolver()};
            var serialized = JsonConvert.SerializeObject(source, settings);
            return JsonConvert.DeserializeObject<T>(serialized);
        }

        public class MyContractResolver : DefaultContractResolver
        {
            protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
            {
                var props = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                                .Select(p => base.CreateProperty(p, memberSerialization))
                            .Union(type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                                        .Select(f => base.CreateProperty(f, memberSerialization)))
                            .ToList();
                props.ForEach(p => { p.Writable = true; p.Readable = true; });
                return props;
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM