Inheritance 使用方法:1。ISerializable with Serializer.Merge/Serialize&;2.ProtoInclude与RuntimeTypeModel。默认值?
我将我的项目转换为使用protobuf net而不是BinaryFormatter。 看起来似乎缺少文档 我还查阅了一些例子 但有些事情我还不清楚,这就是为什么我决定在这里问: 1。关于ISerializable和Serializer.合并/序列化 如果我们从ISerializable继承来进行特定的序列化。 当我读到: 我们必须使用钩子序列化程序。Merge/Serialize 假设我们有课:Inheritance 使用方法:1。ISerializable with Serializer.Merge/Serialize&;2.ProtoInclude与RuntimeTypeModel。默认值?,inheritance,serialization,protocol-buffers,protobuf-net,iserializable,Inheritance,Serialization,Protocol Buffers,Protobuf Net,Iserializable,我将我的项目转换为使用protobuf net而不是BinaryFormatter。 看起来似乎缺少文档 我还查阅了一些例子 但有些事情我还不清楚,这就是为什么我决定在这里问: 1。关于ISerializable和Serializer.合并/序列化 如果我们从ISerializable继承来进行特定的序列化。 当我读到: 我们必须使用钩子序列化程序。Merge/Serialize 假设我们有课: [Serializable] [ProtoContract] public class Anchor
[Serializable]
[ProtoContract]
public class Anchor : ISerializable
{
[ProtoMember(1)]
public int id;
[ProtoMember(2)]
public Ship ship;
...
}
序列化程序.Merge(info,this);必须添加到构造函数锚(SerializationInfo、StreamingContext上下文)
和Serializer.Serialize(info,this);添加到void GetObjectData(SerializationInfo信息、StreamingContext上下文)
因此,我们有:
protected Anchor(SerializationInfo info, StreamingContext context)
{
//for binaryformatter:
Type myType = typeof(Anchor);
foreach (SerializationEntry e in info)
{
FieldInfo f = myType.GetField(e.Name,BindingFlags.NonPublic|BindingFlags.Public|BindingFlags.Public|BindingFlags.Instance);
f.SetValue(this,e.Value);
}
//added for protobuf-net:
Serializer.Merge(info, this);
}
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
//for binaryformatter:
foreach (FieldInfo f in typeof(Anchor).GetFields(BindingFlags.NonPublic|BindingFlags.Public|BindingFlags.Instance))
{
if ((f.Attributes&FieldAttributes.NotSerialized)==0)
info.AddValue(f.Name,f.GetValue(this));
}
//added for protobuf-net:
Serializer.Serialize(info, this);
}
问题:
这是正确的吗?(一个“信息”被序列化程序覆盖了?即binaryformatter不能正常工作?目前我只是尝试使用protobuf net,我更希望binaryformatter也能正常工作)
2。关于使用ProtoInclude和RuntimeTypeModel.Default
假设我们有类消息作为类的基础:class Ack、class HandshakeClientInfo…class命令。
如果我们想序列化消息的子项,正如我从中读到的:
我们应该使用ProtoInclude(“告诉”基类:关于它的子类的类消息),以防我们在编译时知道子类类型——这没关系
对于那些我们在编译时无法确定的子类型(因为它在另一个项目中),我们应该使用RuntimeTypeModel.Default[typeof(Message)].AddSubType(207,typeof(Command))强>
或者使用Type.AssemblyQualifiedName:[ProtoInclude(207,“Trainer.Commands.Command,Simulator,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”)]
我使用ProtobufNetV2(r580)和RuntimeTypeModel.Default[typeof(Message)].AddSubType(207,typeof(Command))的变量;似乎更可取
问题:
但我不明白它应该放在代码中的什么地方?在构造器中还是?
是否允许同时使用ProtoInclude和RuntimeTypeModel.Default?首先,我需要非常清楚protobuf net和ISerializable之间的关系。首先,
ISerializable
仅由BinaryFormatter
使用。protobuf net永远不会查找此接口,也永远不会直接使用此接口。所以,你可能会问,为什么protobuf net会提到这一点
答:因为有些人拥有使用BinaryFormatter所需的现有代码,但希望在内部使用其他代码。一个很好的例子可能是使用远程处理的现有代码。在这里,protobuf-net可以用来实现ISerializable
,基本上取代了BinaryFormatter
。典型用法如下:
protected Anchor(SerializationInfo info, StreamingContext context)
{
Serializer.Merge(info, this);
}
public virtual void GetObjectData(SerializationInfo info,
StreamingContext context)
{
Serializer.Serialize(info, this);
}
然后在内部使用protobuf网络;protobuf net将序列化对象(和任何子数据),并将数据存储在单个字段中;在反序列化过程中,它将反转此操作。ISerializable
接口不用于向protobuf网络中添加附加信息。在大多数情况下,如果您想分别支持protobuf net和BinaryFormatter
,那么构造函数中就不会有序列化程序
/protobuf net代码,您也不需要对任何现有的ISerializable
实现进行任何更改。这仅适用于您希望从内部更改BinaryFormatter
工作方式的非常特定的场景。在这种情况下,您通常会将完全控制权交给protobuf net
关于子类型的问题;是的,您可以将
[ProtoInclude]
与RuntimeTypeModel.Default
结合使用。基本上,默认情况下(可以调整),protobuf net第一次看到类型时,会检查属性。如果有,它将使用这些属性来配置模型。但是,您仍然可以对配置进行所需的任何更改,直到它必须序列化/反序列化该类型,此时它将配置信息烘焙到执行工作的策略中。一旦决定了策略,它就不喜欢你改变配置
因此,配置模型的最佳时间是:应用程序启动时。或者至少,在你开始做任何有趣的事情之前。为了完整性,我应该注意,如果您想完全手动配置模型,您也可以要求它忽略属性(这是非常罕见的)
所以你的台词是:
RuntimeTypeModel.Default[typeof(Message)].AddSubType(207, typeof(Command));
在应用程序启动时就可以了
在某些(罕见的)情况下,您可能会在很久以后发现新类型。出于各种非常复杂的原因,在开始序列化后允许更改现有模型不是很实际,但是:RuntimeTypeModel.Default
只是一个默认实例。在一些更高级的场景中,您可能需要做的是维护您自己的模型,然后根据需要配置一个新的、知识更丰富的模型。因此,您可以使用以下命令,而不是使用RuntimeTypeModel.Default
:
static RuntimeTypeModel serializer = TypeModel.Create();
然后,您可以在以后配置新的设置:
var workInProgress = TypeModel.Create();
// TODO: add whatever you need here
serializer = workInProgress;
var workInProgress = TypeModel.Create();
// TODO: add whatever you need here
serializer = workInProgress;