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
I don't want to use "ProtoInclude" on the BaseClass. (All my classes are distributed independently via nuget packages and having knowledge of child classes in base class breaks that)
编辑 1
序列化现在正在工作! (感谢马克·格拉维尔)
但是,反序列化不是(获取“无法将 BaseClass 类型的 object 转换为 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 用于 链式构建器使用 ,实际上 returns 您传入的同一对象 - 或者具体地说: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
}
附带说明:10
与 20
- 这些并不相互冲突,因为它们(现在)应用于层次结构的不同级别;如果您愿意,它们都可以是 10
或任何其他数字。
序列化时出现“意外的子类型”。
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
I don't want to use "ProtoInclude" on the BaseClass. (All my classes are distributed independently via nuget packages and having knowledge of child classes in base class breaks that)
编辑 1 序列化现在正在工作! (感谢马克·格拉维尔) 但是,反序列化不是(获取“无法将 BaseClass 类型的 object 转换为 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 用于 链式构建器使用 ,实际上 returns 您传入的同一对象 - 或者具体地说: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
}
附带说明:10
与 20
- 这些并不相互冲突,因为它们(现在)应用于层次结构的不同级别;如果您愿意,它们都可以是 10
或任何其他数字。