Mikko Keskitalo
Mikko Keskitalo

Reputation: 21

Deserializing missing type with protobuf.net

I have an application with plugin architecture. The plugins have their own data containers, which all inherit from the base interface IPluginDataStorage. The DataStorage object, which is serialized to preserve state, contains a list of these subclasses along with other data. The DynamicType flag is set to true, as it's not known until run time which plugins are in use.

[Serializable]
[ProtoContract]
public class DataStorage
{
    [ProtoMember(200, DynamicType = true)]
    public List<IPluginDataContainer> PluginDataStorage { get; set; }

When serializing this setup works okay, but I'm having problems deserializing the list reliably. If I try to deserialize the object without having access to all those plugins that were used when it was serialized, I, naturally, get an exception about a missing type.

Unable to resolve type: NOSMemoryConsumptionPlugin.NOSMemoryConsumptionData, NOSMemoryConsumptionPlugin, Version=1.2.0.17249, Culture=neutral, PublicKeyToken=null (you can use the TypeModel.DynamicTypeFormatting event to provide a custom mapping)

The exception gives a hint that I could provide the format through the event, but I don't see how that could be helpful as the problem is that I don't have that type available. What I'd like to do in these cases is to completely ignore deserializing that object. The list item could even default to a dummy instance of the base class in these cases. But how to do this?

Upvotes: 2

Views: 967

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1064324

That (choosing to skip or default) is a fascinating use-case that I don't think I have considered fully; however, you can probably do this yourself, via:

public class NilContainer : IPluginDataContainer {}

and then subscribe to the DynamicTypeFormatting event; if you don't recognise the type, supply typeof(NilContainer).

i.e.

RuntimeTypeModel.Default.DynamicTypeFormatting += (sender, args) =>
{
    Type type;
    if(!yourTypeMap.TryGetValue(args.FormattedName, out type))
    {
        type = typeof (NilContainer);
    }
    args.Type = type;
};

(completely untested)

Upvotes: 1

Related Questions