赞
踩
NakedBrunch
我想实现 引用类型对象
之间的深复制,也就是在新的对象上修改不会影响到老的对象,我用了 C# 提供的 Clone
方法。
- MyObject myObj = GetMyObj(); // Create and fill a new object
- MyObject newObj = myObj.Clone();
但貌似这样行不通,请问该如何正确实现?
craastad
如果你的引用类型对象
是 json 友好的,那你完全可以借助第三方工具将其转为 Json
,比如 Json.NET
,参考如下的 Clone
扩展方法。
- public static T Clone<T>(this T theObject)
- {
- string jsonData = JsonConvert.SerializeObject(theObject);
- return JsonConvert.DeserializeObject<T>(jsonData);
- }
然后像下面这样使用。
NewObject = OldObject.Clone();
Stacked
如果你要快速实现,建议使用对象映射化工具 AutoMapper
, 它是一个高效并且轻量级的将一个对象转为另一个对象,它的底层使用的是 Lambda
表达式树,参考如下代码:
- MyType source = new MyType();
- Mapper.CreateMap<MyType, MyType>();
- MyType target = Mapper.Map<MyType, MyType>(source);
上面的target
就是深copy后的对象,如果你觉得这样还繁琐的化,再封装到一个扩展方法中去。
- public static T Copy<T>(this T source)
- {
- T copy = default(T);
- Mapper.CreateMap<T, T>();
- copy = Mapper.Map<T, T>(source);
- return copy;
- }
然后像下面这样使用。
MyType copy = source.Copy();
Marcell Toth
通常来说,做深层的copy,方法有如下几种。
序列化
本质上来说,序列化是非常慢的一种方式,而且还限制重重,比如说:
BinaryFormatter 需要引用类型必须实现 Serializable
特性。
JsonConverter 需要引用类型必须有无参构造函数。
表达式树
要先加速,可以使用 Expression Tree
或者 Reflection.Emit
来动态生成深复制代码,但这种原始的方式实现起来特别麻烦,我为此专门写了一个映射工具,参见 github:https://github.com/marcelltoth/ObjectCloner
实现起来非常方便,参考如下代码:
var clone = ObjectCloner.DeepClone(original);
我的方法 ~3x
于 Reflection, ~12x
于 Newtonsoft.Json 。
其实 Dapper 用的就是 Emit
来实现高速映射, AutoMapper
用的是 Expresstion Tree
实现高速映射,大家有兴趣可以了解下。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。