我有一个Dictionary<string,object>
,我在其中保存要解析的对象到我的插件系统,其中一些对象需要是副本而不是原始对象,所以我使用这个DeepClone方法:
public static T DeepCloneJSON<T>(this T Obj)
{
var text = JsonSerializer.Serialize(Obj);
return JsonSerializer.Deserialize<T>(text);
}
例如,如果我这样做:
var dict = new Dictionary<string,object>(){
{"someKey",new List<MyClass>(){new MyClass()}}
}
var copy = dict["someKey"].DeepCloneJSON();
var cast = (List<MyClass>)copy;
我有一个系统。InvalidCastException,但如果我使用MemoryStream DeepCopy方法,我不会得到这个异常,比如这个:
public static T DeepCloneMemoryStream<T>(this T obj)
{
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Position = 0;
return (T)formatter.Deserialize(ms);
}
}
所以,我想知道为什么我使用基于System.text.json的DeepClone方法来获得这个异常,以及是否可以使用System.text.jsn来实现这一点,因为在我的测试中,它比基于MemoryStream的onde更快,使用更少的内存。
即使T
是对象,您的DeepCloneMemoryStream
也会通过反射重新创建确切的类型。
通过JSON字符串的DeepCloneJSON
往返会丢失类型信息,因此反序列化需要指定确切的类型。在您的情况下,您只将object
作为T
传递,因此您得到的是JsonElement
而不是List<MyClass>
。
如果您更改呼叫方式,以下内容将起作用:
var copy = DeepCloneJSON((List<MyClass>)dict["someKey"]);
或者,更改您的实现,使反序列化根据Obj
的实际类型而不是指定的类型T
进行——这将具有与其他实现类似的效果,其中T
仅用于强制转换。
public static T DeepCloneJSON<T>(T Obj)
{
var text = JsonSerializer.Serialize(Obj);
return (T)JsonSerializer.Deserialize(text, Obj.GetType());
}
完全不同的方法
通过在各种使用反射-发射或表达式树等技术来避免序列化的开源NuGet包中进行选择,可以避免强制转换异常、序列化和反序列化的开销,以及可能出现的问题(例如,私有成员、不可序列化实例等(。
一个例子是评论中建议的FastDeepCloner。还有其他几个提供了类似的功能。