与所有属性一样,属性中包含的类型信息适用于泛型类型定义中的所有封闭类型。因此,您实际定义的(对 protobuf-net)是:
BaseClass
: GenericBaseClass<object>
: GenericDerivedClass<object>
: DerivedClass1
: DerivedClass2
: GenericDerivedClass<string>
: DerivedClass1
: DerivedClass2
: GenericBaseClass<string>
: GenericDerivedClass<object>
: DerivedClass1
: DerivedClass2
: GenericDerivedClass<string>
: DerivedClass1
: DerivedClass2
正如您所看到的,有很多重复项 - 这显然令人困惑。由于属性参数不能使用类型参数,因此可以选择添加某种奇怪的谓词机制,这在我看来非常令人困惑。 IMO,最好手动对此进行建模(删除ProtoInclude
属性)。我suspect您想要的模型是:
BaseClass
: GenericBaseClass<object>
: GenericDerivedClass<object>
: DerivedClass2
: GenericBaseClass<string>
: GenericDerivedClass<string>
: DerivedClass1
protobuf-net 可以使用它,但是explain该模型需要“v2”并且RuntimeTypeModel
:
另请注意object
对于protobuf来说有点问题; protobuf-net 可以使用动态类型选项来伪造它,但这......并不理想。它肯定不能序列化object
,所以为了测试我替换了一个字符串。另请注意BaseProperty1
, BaseProperty2
and AdditionalProperty
目前尚未标记为序列化,但可能很简单。
Anyway:
RuntimeTypeModel.Default[typeof(BaseClass)]
.AddSubType(10, typeof(GenericBaseClass<object>))
.AddSubType(11, typeof(GenericBaseClass<string>));
RuntimeTypeModel.Default[typeof(GenericBaseClass<object>)]
.AddSubType(10, typeof(GenericDerivedClass<object>));
RuntimeTypeModel.Default[typeof(GenericBaseClass<object>)][5].DynamicType = true; // object!
RuntimeTypeModel.Default[typeof(GenericDerivedClass<object>)]
.AddSubType(10, typeof(DerivedClass2));
RuntimeTypeModel.Default[typeof(GenericBaseClass<string>)]
.AddSubType(10, typeof(GenericDerivedClass<string>));
RuntimeTypeModel.Default[typeof(GenericDerivedClass<string>)]
.AddSubType(10, typeof(DerivedClass1));
DerivedClass2 i = new DerivedClass2() { BaseProperty1 = 1, BaseProperty2 = 2, DerivedClass2Property = 3, ResponseProperty = "some string" };
using (var file = System.IO.File.Create("test.bin"))
{
ProtoBuf.Serializer.Serialize(file, i);
}
using (var file = System.IO.File.OpenRead("test.bin"))
{
var o = ProtoBuf.Serializer.Deserialize<DerivedClass2>(file);
}
你不have to use RuntimeTypeModel.Default
- 事实上,我建议使用(并缓存)单独的类型模型;但Serializer.Serialize
指向默认模型。如果您创建自定义模型(TypeModel.Create
)只需将其存储在某处并使用Serialize
等从那里。