序列化和元数据

如果你的应用会序列化和反序列化对象,你可能需要将条目添加到运行时指令 (.rd.xml) 文件以确保必要的元数据在运行时间存在。 有两类序列化序列化程序,并且每一类要求在你的运行时指令文件中进行不同处理:

  • 基于反射的第三方序列化程序。 这些程序要求修改你的运行时指令文件,我们会在后面一部分对其进行讨论。

  • 在 .NET Framework 类库中找到基于非反射的序列化程序。 这些程序可能要求修改运行时指令文件,我们会在 Microsoft 序列化程序部分对其进行讨论。

第三方序列化程序

第三方序列化程序(包括 Newtonsoft.JSON)通常基于反射。 考虑到一个序列化数据的二进制大型对象 (BLOB),该数据中的字段通过按名称查找目标类型的字段被分配到了一个具体类型。 在最低限度下,使用这些库时,在 List<Type> 集合中尝试序列化或反序列化的每个 Type 对象都会出现 MissingMetadataException 异常。

处理由这些序列化程序的丢失元数据引起的最简单的方法是,收集将被用在单独命名空间(比如 App.Models)下序列化中的类型,并向其直接应用一个 Serialize 元数据指令:

<Namespace Name="App.Models" Serialize="Required PublicAndInternal" />

有关示例中所使用语法的信息,请参阅 <Namespace> 元素

Microsoft 序列化程序

尽管 DataContractSerializerDataContractJsonSerializerXmlSerializer 类并不依赖反射,它们需要在要得到序列化或反序列化的对象的基础上生成的代码。 每个序列化程序的重载构造函数包含一个指定需要得到序列化或反序列化的 Type 参数。 你在代码中如何指定该类型定义了你必须进行的操作,这将在以下两部分中讨论到。

构造函数中使用的 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

如果你调用了这些序列化类的一个构造函数并在提供给构造函数 Type 参数的表达式外部使用了 C# typeof 运算符(如以下代码所示),则 .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> 元素

另请参阅