如果应用序列化和反序列化对象,则可能需要将条目添加到运行时指令(.rd.xml)文件中,以确保运行时存在必要的元数据。 有两类序列化程序,每个类别都需要在运行时指令文件中进行不同的处理:
基于反射的第三方序列化程序。 这些要求修改运行时指令文件,并在下一部分进行讨论。
在 .NET Framework 类库中找到的非反射序列化程序。 这些操作可能需要修改运行时指令文件,并在 Microsoft序列化程序 部分中讨论。
第三方序列化程序
第三方序列化程序(包括Newtonsoft.JSON)通常基于反射。 给定序列化数据的二进制大型对象(BLOB),通过按名称查找目标类型的字段,将数据中的字段分配给具体类型。 至少,使用这些库时,每次尝试在 集合中序列化或反序列化 Type 对象时,都会导致 List<Type>
异常。
解决这些序列化程序缺少元数据导致的问题的最简单方法是收集将在单个命名空间(例如 App.Models
)下序列化中使用的类型,并向其应用 Serialize
元数据指令:
<Namespace Name="App.Models" Serialize="Required PublicAndInternal" />
有关示例中使用的语法的信息,请参阅 <Namespace> 元素。
Microsoft 序列化程序
DataContractSerializer虽然和DataContractJsonSerializerXmlSerializer类不依赖于反射,但它们确实需要基于要序列化或反序列化的对象生成代码。 每个序列化程序的重载构造函数中包含一个参数,用于指定要序列化或反序列化的类型。 如何在代码中指定该类型会定义您必须采取的操作,如后续两节中所述。
构造函数中使用的“typeof”
如果调用这些序列化类的构造函数并在方法调用中包含 C# typeof 运算符,无需执行任何其他工作。 例如,在对序列化类构造函数的以下每个调用中, typeof
关键字用作传递给构造函数的表达式的一部分。
XmlSerializer xmlSer = new XmlSerializer(typeof(T));
DataContractSerializer dataSer = new DataContractSerializer(typeof(T));
DataContractJsonSerializer jsonSer = new DataContractJsonSerializer(typeof(T));
.NET Native 编译器将自动处理此代码。
在构造函数外部使用的 typeof
如果调用这些序列化类的构造函数并使用 C# typeof 运算符,则提供给构造函数的 Type 参数的表达式之外,如以下代码所示,.NET Native 编译器无法解析类型:
Type t = typeof(DataSet);
XmlSerializer ser = new XmlSerializer(t);
在这种情况下,必须通过添加如下所示的条目来指定运行时指令文件中的类型:
<Type Name="DataSet" Browse="Required Public" />
同样,如果调用构造函数(例如 XmlSerializer(Type, Type[]) 并提供其他 Type 对象的数组)来序列化,如以下代码中所示,.NET Native 编译器无法解析这些类型。
XmlSerializer xSerializer = new XmlSerializer(typeof(Teacher),
new Type[] { typeof(Student),
typeof(Course),
typeof(Location) });
将每种类型的条目添加到运行时指令文件,例如:
<Type Name="t" Browse="Required Public" />
有关示例中使用的语法的信息,请参阅 <Type> Element。