I'm in the process of porting a regular .Net 4.5 library over to the Portable Class Library profile 111 - which includes Windows Store, Windows Phone, Xamarin.Android and Xamarin.iOS and Desktop. Part of that framework is a custom serialization system to deal with some of the limitations from the .Net ones.
Data will be serialized across platforms, meaning that I might serialize an object running in .Net 4.5 on Desktop and deserialize it in a Windows Store app. This fact combined with the Evolved Reflection API creates an unfortunate serialization problem with Type and TypeInfo.
In normal operation, the serializer asks an object for its type using GetType
and decides how to proceed based on that. If it turns out to be a reference to a Type
, a string ID will be serialized that can be used for resolving the Type
during deserialization, other cases are handled differently. As the serializer also handles metadata about each serialized object, you will never need to tell it what kind of object you expect, but instead will receive a fully deserialized object as is.
The problem arises from the fact that, in .Net 4.5 at runtime, GetType()
on a Type
reference will return RuntimeType
, which derives from TypeInfo
, which derives from Type
, MemberInfo
and so on.. so when running in .Net 4.5, the object will be both Type
and TypeInfo
. Neither does it matter, nor is it possible to distinguish between them.
However, this is not the case when deserializing the data stream in a Windows Store app, where Type
and TypeInfo
are completely distinct classes. Which one should be retrieved when resolving the string ID? Type
or TypeInfo
?
The reason it matters is that both users and the serializer itself always expect to deserialize the same kind of object that was previously serialized, but because Type
and TypeInfo
cannot be distinguished in .Net 4.5, this information is missing during deserialization in a Windows Store app. Making a choice in favor of one of those types will cause errors when the other would have been expected, and there is no way to predict which one is expected.
Is there any way to solve this?
So far, I've been considering various options, like scattering a lot of "implicit cast"-like checks and conversions throughout the serializer code, but this doesn't really cover all cases and especially not the ones involving unsuspecting users who will get an object of the wrong type.. any advice or experience on this would be highly appreciated!
Take a look at how LightInject handles this scenario using conditional compilation.