如何在C#中使用System.Reflection對象的深層副本?使用System.Reflection對象的深層副本?
回答
一個簡單的方法是使用JSON:
public static T DeepClone<T>(T source)
{
var serialized = JsonConvert.SerializeObject(source);
return JsonConvert.DeserializeObject<T>(serialized);
}
這確實反映了你。顯然,它不適用於任何對非託管對象有句柄等任何事情。
(可以使用的NuGet來Newtonsoft.Json安裝到你的項目。)
默認的Json不會連載私有字段。
可以解決這個問題,像這樣:
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;
}
}
這裏有一個完整的示例控制檯應用程序,演示如何與私人領域的任意類可以被克隆。需要注意的是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;
}
}
}
}
這不適用於任何對象。對象必須準備好序列化。 – Sinatr
@Sinatr它將適用於許多對象 - 如果您需要使用遞歸,那麼該對象無論如何都必須是可序列化的。 –
@Sinatr JSON.NET是不是像DataContractJsonSerializer ... –
- 1. 派生python對象的深層副本
- 2. 對象圖的JavaScript深層副本
- 3. 2d對象數組的深層副本
- 4. QML ListModel的深層副本
- 5. NSMutableDictionary的深層副本
- 6. 片段的深層副本
- 7. 使用深層副本實現遞歸
- 8. 作爲全局對象的QScriptValue的深層副本
- 9. OpenCV cv深層副本::墊
- 10. 重載=運算符時返回對象的深層副本
- 11. 是否存在無法創建深層副本的對象?
- 12. 如何做NHibernate對象的深層副本?
- 13. 對象和數組的ECMAScript5深層副本
- 14. PHP數組引用的深層副本
- 15. 深層副本對象陣列屬性與jQuery
- 16. SqlCommand.Clone()是否創建深層副本或淺層副本?
- 17. 如何使自定義對象的NSMutableArray屬性的深層副本
- 18. OrderedDict兒童的深層副本
- 19. C指針結構的深層副本
- 20. 熊貓面板的深層副本?
- 21. 製作字典的深層副本
- 22. 鏈接列表C++的深層副本
- 23. 可變的NSMutableDictionary深層副本
- 24. 一個NSMutableDictionary的深層可變副本
- 25. Ruby中數組的深層副本
- 26. 如何執行char *的深層副本?
- 27. 教條記錄的深層副本
- 28. 二叉樹的深層副本
- 29. kxml節點的深層副本(java me)
- 30. 列表的深層副本<T>
你爲什麼需要'反思?以及目前爲止您嘗試的內容 – Habib
屬性/字段的遞歸。問題是要包含哪些內容,如何處理私有字段等等。因此,通過序列化現有序列化和反序列化新序列化,「克隆」對於專門準備好的序列化對象更容易。 – Sinatr