Serialization and metadata

If your app serializes and deserializes objects, you may need to add entries to your runtime directives (.rd.xml) file to ensure that the necessary metadata is present at run time. There are two categories of serializers, and each requires different handling in your runtime directives file:

  • Reflection-based third-party serializers. These require modifications to your runtime directives file, and are discussed in the next section.

  • Non-reflection-based serializers found in the .NET Framework class library. These may require modifications to your runtime directives file, and are discussed in the Microsoft serializers section.

Third-party serializers

Third-party serializers, including Newtonsoft.JSON, typically are reflection-based. Given a binary large object (BLOB) of serialized data, the fields in the data are assigned to a concrete type by looking up the fields of the target type by name. At a minimum, using these libraries causes MissingMetadataException exceptions for each Type object that you try to serialize or deserialize in a List<Type> collection.

The easiest way to address issues caused by missing metadata for these serializers is to collect types that will be used in serialization under a single namespace (such as App.Models) and apply a Serialize metadata directive to it:

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

For information about the syntax used in the example, see <Namespace> Element.

Microsoft serializers

Although the DataContractSerializer, DataContractJsonSerializer, and XmlSerializer classes do not rely on reflection, they do require code to be generated based on the object to be serialized or deserialized. The overloaded constructors for each serializer include a Type parameter that specifies the type to be serialized or deserialized. How you specify that type in your code defines the action you must take, as discussed in the next two sections.

typeof used in the constructor

If you call a constructor of these serialization classes and include the C# typeof operator in the method call, you do not have to do any additional work. For example, in each of the following calls to a serialization class constructor, the typeof keyword is used as part of the expression passed to the constructor.

XmlSerializer xmlSer = new XmlSerializer(typeof(T));
DataContractSerializer dataSer = new DataContractSerializer(typeof(T));
DataContractJsonSerializer jsonSer = new DataContractJsonSerializer(typeof(T));

The .NET Native compiler will automatically handle this code.

typeof used outside the constructor

If you call a constructor of these serialization classes and use the C# typeof operator outside the expression supplied to the constructor's Type parameter, as in the following code, the .NET Native compiler cannot resolve the type:

Type t = typeof(DataSet);
XmlSerializer ser = new XmlSerializer(t);

In this case, you must specify the type in the runtime directives file by adding an entry like this:

<Type Name="DataSet" Browse="Required Public" />

Similarly, if you call a constructor such as XmlSerializer(Type, Type[]) and provide an array of additional Type objects to serialize, as in the following code, the .NET Native compiler cannot resolve these types.

XmlSerializer xSerializer = new XmlSerializer(typeof(Teacher),
                            new Type[] { typeof(Student),
                                         typeof(Course),
                                         typeof(Location) });

Add entries such as the following for each type to the runtime directives file:

<Type Name="t" Browse="Required Public" />

For information about the syntax used in the example, see <Type> Element.

See also