Using protobuf-net, what is the correct way to serialize a derived type that implements an interface?

StackOverflow https://stackoverflow.com/questions/14386323

  •  16-01-2022
  •  | 
  •  

문제

I realize that there are similar questions here, but none that asks this quite as straightforwardly as what I need, probably because of my lack of protobuf experience. I am transcoding for enyim's caching client, and having trouble figuring out how to make a class that is both derived and implementing an interface de/serialize correctly.

For a sample like this

public class BaseClass
{
}

public interface ISomeRules
{
}

public class DerivedClass : BaseClass, ISomeRules
{
}

public class ThirdClass
{
    ISomeRules ruleUser;
}

I want to do something like this, because I generally use attributes everywhere

[ProtoContract
,ProtoInclude(101,typeof(DerivedClass))
]
public class BaseClass
{
}

[ProtoContract
,ProtoInclude(102,typeof(DerivedClass))
]
public interface ISomeRules
{
}

[ProtoContract]
public class DerivedClass : BaseClass, ISomeRules
{
}

[ProtoContract]
public class ThirdClass
{
    [ProtoMember(1)]
    ISomeRules ruleUser;
}

but it fails caching silently. If as some have suggested I remove the ProtoContract attribute from ISomeRules, the deserialization fails.

Is this doable using protobuf-net? What is the right way to do this? Should I be using the TypeModel (which I do not master, but which simple tests indicate has the same problem) instead? Or a combination of TypeModel and attributes?

도움이 되었습니까?

해결책

The interface support in protobuf-net is intended for limited scenarios, you you are basically working to an interface-based model, in particular for nested members. For example:

[ProtoContract]
public class Foo {
    [ProtoMember(1)]
    public IBar Bar {get;set;}
}

In the above, we want to be able to serialize the Bar, but we might not know a lot about it. In fact, if Foo guarantees to return a non-null value from Bar, protobuf-net doesn't even need to know anything about concrete types etc - it can just go ahead and populate the object it is given.

In your example, the root object is unquestionably BaseClass. I would suggest that ISomeRules is anciliary, and does not need to be mentioned at all in the model. However, if you want to populate members that are only exposed via ISomeRules, then you might try (untested):

[ProtoMember(n)]
private ISomeRules Rules { get { return this; } }

This then exposes the ISomeRules information, but spoofing it as a sub-object. It is, at the minimum, worth a try; p

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top