根据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
参数中指定类型的任何对象。
我的问题是:
如果序列化程序可以正确编写任一参数中指定类型的对象,那么拥有第一个参数的目的是什么?
是否有任何特殊情况,第一个参数被区别对待,或者对序列化器有特殊用途?
答案 0 :(得分:0)
我相信这个想法是知道期望的类型将有助于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
调用它并向其发送{{ 1}}要序列化,它正在检查是否TypeA
,确定它不是预期的类型,并打印出额外的,不必要的类型信息。