Serializing object with interface as property type in MessagePack
Asked Answered
U

1

7

I am trying to use MessagePack to serialize an object that has a property of an interface type. When I call Pack, it throws SerializationException that says a serializer is not defined for the interface.

Code example:

namespace ConsoleApplication1
{
  // interfaces and classes declaration

  public interface IDummyInterface { }

  public class DummyObject : IDummyInterface
  {
    public string Value { get; set; }
  }

  public class SmartObject
  {
    public string Name { get; set; }

    IDummyInterface DummyOne { get; set; }
  }

  // in main
  var mySmartObject = new SmartObject() { Name = "Yosy", DummyOne = new DummyObject() { Value = "Value"} };

  using(var stream = new MemoryStream())
  {
    var serializer = MessagePackSerializer.Create<SmartObject>();
    serializer.Pack(mySmartObject, stream); // => This code throws the exception
  }
}

Can I tell MessagePack which serializer to use for IDummyInterface and tell it to act as DummyObject?

Underwear answered 29/9, 2013 at 17:21 Comment(0)
C
1

It seems to me you are using msgpack-cli. To make it work, basically there are two ways to do it.

1. Use MessagePackKnownTypeAttribute

This one is easy and straightforward.

public class SmartObject
{
    public string Name { get; set; }

    [MessagePackKnownType("d", typeof(DummyObject))]
    public IDummyInterface DummyOne { get; set; } // Need to make this property public
}

2. Implement custom serializer

If you want a clean model class without reference to MsgPack library, you can do the following, but you need to figure out a way to serialize/deserialize SmartObject (efficiently).

public class SmartObjectSerializer : MessagePackSerializer<SmartObject>
{
    public SmartObjectSerializer(SerializationContext ownerContext) : base(ownerContext)
    {
    }

    protected override void PackToCore(Packer packer, SmartObject objectTree)
    {
        var str = ToString(objectTree); // TODO: Just an example
        packer.Pack(str);
    }

    protected override SmartObject UnpackFromCore(Unpacker unpacker)
    {
        var str = unpacker.LastReadData.AsStringUtf8(); // TODO: Just an example
        return new SmartObject
        {
            // TODO: Initialize based on str value
        };
    }
}

// In main
var context = new SerializationContext();
context.Serializers.RegisterOverride(new SmartObjectSerializer(context));

var serializer = MessagePackSerializer.Get<SmartObject>(context);
// The rest is the same

There are some sample codes you may be interested to take a look.

Commend answered 16/10, 2020 at 1:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.