'类型'当给定已知类型时,在DataContractJsonSerializer中
本文关键字:类型 DataContractJsonSerializer | 更新日期: 2023-09-27 18:13:23
对于MSDN,构造函数DataContractJsonSerializer(Type, IEnumerable<Type>)
的第一个参数定义为被序列化或反序列化的实例的类型
然而,我最近在一些产品代码中遇到了一个错误,但随后很快意识到序列化工作如预期。它的简化版本是:
var knownTypes = new[] { typeof(TypeA), typeof(TypeB) };
// Bug below. Should be 'otherType = typeof(C)'
// Always sets otherType to System.RuntimeType
var otherType = typeof(TypeC).GetType();
var serializer = new DataContractJsonSerializer(otherType, knownTypes);
using(var output = new MemoryStream())
{
serializer.WriteObject(output, new TypeA());
output.Position = 0;
var copy = (TypeA) serializer.ReadObject(output);
}
这是因为序列化器将成功写入任何具有type
参数或knownTypes
参数中指定类型的对象。
我的问题是
如果序列化器可以正确地写入两个实参中指定的类型的对象,那么使用第一个实参的目的是什么?
是否有特殊情况,第一个参数被区别对待,或者对序列化器有特殊用途?
我相信这个想法是,知道什么类型是预期将有助于DataContractJsonSerializer
在多态操作的情况下打印出类型信息。
class Foo
{
public string a { get; set; }
}
class Bar : Foo
{
public string b { get; set; }
}
对于我剩下的例子,我们假设您按照如下方式初始化序列化器:
var s = new DataContractJsonSerializer(typeof(Foo), new Type[] { typeof(Bar) });
s.EmitTypeInformation = EmitTypeInformation.AsNeeded;
这样做之后,你开始使用它:
- 这样做之后,你给它传递一个
Foo
的实例来序列化,它将序列化一个单一的属性,a
,这将是。{ "a" : "valueA" }
- 现在,向它传递一个
Bar
的实例。稍等,typeof(Foo) != typeof(Bar)
。序列化程序看到这一点,并认识到反序列化客户端可能会对此感到困惑,或者最好的情况是,可能会跳过一些数据。因此,它输出显式的类型信息。{ "__type" : "Bar", "a : "valueA", "b", "valueB" }
现在让我们假设你给它传递一个完全随机的东西的实例,比如,
DateTime
。同样,它检查并看到,哇,typeof(DateTime) != typeof(Foo)
,所以这里客户端可能会严重混淆。因此,又添加了"__type"属性。这使我们尽可能地摆脱了风险。所以在无bug的使用中,它主要只是通过序列化来保持多态参数的问题。
此外,它不使用Type.IsAssignableFrom(Type)
,因为这是不必要的,会导致异常,可能会造成不必要的挫折,所以当你的代码用Type
类型调用它并向它发送TypeA
来序列化时,它正在检查Type == value.GetType()
,决定它不是预期的类型,并打印出额外的,不必要的类型信息。