Marc在stackoverflow上提到,在protobuf-net的v2中,可以使用ProtoInclude属性(或类似方法)来序列化/反序列化类层次结构,而不需要在基类中指定每个子类型。这已经实现了吗?我们有一个可以在外部库中派生的插件接口,所以没有办法知道派生类型是什么。虽然我们可以在类型之间保持唯一的编号,但我在网上找不到任何示例,除了使用ProtoInclude属性之外,它需要指定一个子类型。
如果我不知道子类型是什么,我该如何使用protobuf-net实现继承呢?
发布于 2011-06-06 13:33:49
如果你不能在属性中指定子类型(因为它在编译时是未知的),你有两个选择(这两个选择都只适用于"v2",测试版):
RuntimeTypeModel,而不是静态Serializer方法(现在只是RuntimeTypeModel.Default的快捷方式);告诉模型关于继承(下面的示例)DynamicType = true添加到有问题的[ProtoMember(...)] <代码>H29<代码>G210第二个不是非常纯粹的protobuf -它嵌入了类型信息,我并不是很喜欢,但是人们只是一直在请求。第一个是我的首选。要在运行时添加子类型:
var model = TypeModel.Create();
var type = model.Add(typeof(YourBaseType), true);
var subTypeA = model.Add(typeof(SomeSubType), true);
var subTypeB = model.Add(typeof(SomeOtherSubType), true);
type.AddSubType(4, typeof(SomeSubType));
type.AddSubType(5, typeof(SomeOtherSubType));上面的true意思是“使用普通规则自动添加成员属性”--如果你愿意,你也可以控制它并手动指定属性(等)。
请注意,TypeModel应该被缓存和重用(而不是为需要序列化的对象创建),因为它包含一些用于生成方法的"emit“代码。重用它会更快,并且需要更少的内存。类型模型是线程安全的,可用于在不同线程上同时序列化/反序列化多个流。
发布于 2012-11-14 07:44:14
为了进一步扩展Marc的答案,特别是处理RuntimeTypeModel,这是一种编写它的方法:
RuntimeTypeModel.Default[typeof(BaseClass)].AddSubType(20, typeof(DerivedClass));如果您有更多从派生类派生的类,请像这样将它们链接起来
RuntimeTypeModel.Default[typeof(DerivedClass)].AddSubType(20, typeof(DerivedFromDerivedClass ));诸若此类。
然后,您可以使用Serializer.Serialize(file,object),就像您通常使用protobuf-net一样。
这可以跨项目和名称空间工作。
发布于 2013-09-24 17:46:35
通过添加helper扩展方法:
public static class RuntimeTypeModelExt
{
public static MetaType Add<T>(this RuntimeTypeModel model)
{
var publicFields = typeof(T).GetFields().Select(x => x.Name).ToArray();
return model.Add(typeof(T), false).Add(publicFields);
}
}您可以简化子类型注册,如下所示:
private static RuntimeTypeModel CreateModel()
{
var model = TypeModel.Create();
model.Add<ExportInfo>();
model.Add<RegistrationInfo>();
model.Add<FactorySetupInfo>()
.AddSubType(101, model.Add<ServiceSetupInfo>().Type)
.AddSubType(102, model.Add<GenericWrapperSetupInfo>().Type)
.AddSubType(103, model.Add<DecoratorSetupInfo>().Type);
return model;
}https://stackoverflow.com/questions/6247513
复制相似问题