繁体   English   中英

protobuf - 使用带有继承的 protobuf-net 进行序列化

[英]protobuf - serialization using protobuf-net with inheritance

序列化时获取“意外子类型”。

var model = RuntimeTypeModel.Create();
var baseType = model.Add(typeof(BaseClass), true, CompatibilityLevel.Level300);
var child = baseType.AddSubType(10, typeof(ChildOfBase));
child.AddSubType(20, typeof(GrandChildToBase));
using (var stream = new MemoryStream())
{                                  
    model.Serialize(stream, grandChildInstance); //ERROR : Unexpected sub type GrandChildToBase
}

获取“意外的子类型 GrandChildToBase” 注意:虽然我将 CompatLevel 设置为 300,但默认为 200。我使用的是 3.0.101 版

我不想在 BaseClass 上使用“ProtoInclude”。 (我所有的类都是通过 nuget 包独立分发的,并且在基类中断中有子类的知识)

编辑 1序列化现在正在运行! (感谢 Marc Gravell)但是,反序列化不是(获取“无法将 BaseClass 类型的对象强制转换为 GrandChildToBase”)。

var model = RuntimeTypeModel.Create();
model.DefaultCompatibilityLevel = CompatibilityLevel.Level300;
var baseType = model.Add(typeof(BaseClass));
var childType = model.Add(typeof(ChildOfBase));
model.Add(typeof(GrandChildToBase)); // don't need to capture result of this one

baseType.AddSubType(10, typeof(ChildOfBase));
childType.AddSubType(20, typeof(GrandChildToBase));
byte[] result = null;
using (var stream = new MemoryStream())
{
    GrandChildToBase grandChildInstance = new();
    model.Serialize(stream, grandChildInstance);
    result = stream.ToArray();
}
using (var stream = new MemoryStream(result))
    {                   
        var payloadObj = Serializer.Deserialize<GrandChildToBase>(stream); ***//ERROR: "Unable to cast object of type BaseClass to GrandChildToBase"***                  
    }

编辑 2根据@Marc Gravell 的澄清,我需要使用自定义“模型”而不是“默认”序列化程序。

这里的错误是AddSubType API 用于链式构建器使用,并有效地返回您传入的相同对象- 或者特别是: AddSubType的结果不是表示子类型的MetaType 你可以通过以下方式看到:

var child = baseType.AddSubType(10, typeof(ChildOfBase));
Console.WriteLine(ReferenceEquals(child, baseType)); // outputs True

这意味着当你做

child.AddSubType(20, typeof(GrandChildToBase));

你有效地将GrandChildToBase添加到BaseClass ,而不是ChildOfBase

我承认图书馆应该在.AddSubType(20, typeof(GrandChildToBase))步骤中清楚地告诉你这一点! 我会检查我们是否可以在那里添加断言。

然而! 要修复代码:

var model = RuntimeTypeModel.Create();
model.DefaultCompatibilityLevel = CompatibilityLevel.Level300;
var baseType = model.Add(typeof(BaseClass));
var childType = model.Add(typeof(ChildOfBase));
model.Add(typeof(GrandChildToBase)); // don't need to capture result of this one

baseType.AddSubType(10, typeof(ChildOfBase));
childType.AddSubType(20, typeof(GrandChildToBase));
using (var stream = new MemoryStream())
{
    GrandChildToBase grandChildInstance = new();
    model.Serialize(stream, grandChildInstance); //ERROR : Unexpected sub type GrandChildToBase
}

附带说明: 1020 - 这些并不相互冲突,因为它们(现在)应用于层次结构的不同级别; 如果您愿意,它们都可以是10或任何其他数字。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM