<MyClass> 从对象转换回列表将返回 System.InvalidCastException C#



我有一个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。还有其他几个提供了类似的功能。

最新更新