Serializing a Collection of Interface Objects with Protobuf-Net

I have the following class definitions:

[ProtoInclude(2, typeof(Foo))]
public interface IFoo
{
    double Bar { get; }
}



[ProtoContract]
public class Foo : IFoo
{
    [ProtoMember(1)]
    private double _bar
    {
        get { return Bar / 10; }
        set { Bar = 10 * value; }
    }

    public double Bar { get; private set; }
}



[ProtoContract]
public class MyClass
{
    [ProtoMember(1, OverwriteList = true)]
    public IReadOnlyList<IFoo> Foos { get; private set; }
}

      

When I try to serialize a MyClass object using protobuf-net, I get an exception:

System.InvalidOperationException: Failed to prepare serializer for: MyNamespace.MyClass ----> System.InvalidOperationException: no serializer is defined for type: MyNamespace.IFoo

In my case, I know that the specific type of elements stored in MyClass.Foos is Foo. How can I tell protobuf to use the type Foo wherever it sees the type IFoo? Alternatively, how can I do this, include Foo as one of the classes available to implement IFoo on the collection?

- EDIT -

The answer from Sam is close enough to reveal another problem with this approach. Namely, it is not possible to serialize a property of type IReadOnlyList <T> using protobuf-net . However, there is an easy workaround as the list is created in the constructor of MyClass. Hence, MyClass can change to the following:

[ProtoContract]
public class MyClass
{
    [ProtoMember(1, OverwriteList = true)]
    private List<IFoo> MutableFoos { get; set; }

    public IReadOnlyList<IFoo> Foos
    {
        get { return MutableFoos; }
    }
}

      

However, MyClass serialization still fails with the message "System.InvalidOperationException: No matching conversion operator found for surrogate: MyNamespace.IFoo / MyNamespace.Foo".

+3


source to share


1 answer


I've never been able to get this to work when an interface class was used in the serialized member. Instead, I had to put the concrete class on the list type. The following is what ultimately worked for me:

[ProtoContract]
public class MyClass
{
    [ProtoMember(1, OverwriteList = true)]
    private List<Foo> MutableFoos { get; set; }

    public IReadOnlyList<IFoo> Foos
    {
        get { return MutableFoos; }
    }
}

      



Note that the type of the serialized element is List<Foo>

instead of List<IFoo>

. I've never figured out how to get the latter to work.

0


source







All Articles