如何将已知类型的列表动态添加到 Protobuf-net 格式化程序?
在一个项目中,我当前正在使用 DataContractSerializer
来序列化我的数据。出于性能原因,我想使用 Protobuf 代替。 我使用序列化程序在数据库中存储 blob,并且我希望保留 WCF 的数据版本控制功能,以便在项目在现实世界中发布后更轻松地处理数据协定修改。
这些 blob 的数据契约在编译时是未知的。 (配置文件中指定了“扩展”列表,因此扩展注册了它们在运行时知道的 DataContracts)
然而,似乎告诉 protobuf 已知类型的唯一方法是使用 [ProtoIninclude]
属性。
更具体地说,这是我想要序列化的示例。
[DataContract]
public class Mydata
{
[DataMember(Order = 1)]
public int Saved
{
get;
set;
}
}
[DataContract]
public class Container
{
[DataMember(Order = 1)]
public object Data
{
get;
set;
}
}
使用 DataContractSerializer
这里我是如何做的:
[TestMethod]
public void SerializeWithDataContractSerializer()
{
var container = new Container()
{
Data = new Mydata()
{
Saved = 1
}
};
DataContractSerializer serializer = new DataContractSerializer(typeof(Container), new[] { typeof(Mydata) });
var ms = new MemoryStream();
serializer.WriteObject(ms, container);
ms.Position = 0;
var containerSerialized = (Container)serializer.ReadObject(ms);
Assert.AreEqual(((Mydata)container.Data).Saved, ((Mydata)containerSerialized.Data).Saved);
}
使用 protobuf
这里我想如何做(但不可能 Serializer.CreateFormatter
不采用 knownTypes
参数):
[TestMethod]
public void SerializeWithProtoBuf()
{
var container = new Container()
{
Data = new Mydata()
{
Saved = 1
}
};
var formatter = Serializer.CreateFormatter<Container>(new[] { typeof(Mydata) });
var ms = new MemoryStream();
formatter.Serialize(ms, container);
ms.Position = 0;
var containerSerialized = (Container)formatter.Deserialize(ms);
Assert.AreEqual(((Mydata)container.Data).Saved, ((Mydata)containerSerialized.Data).Saved);
}
有解决方案吗?
In a project, I'm currently using a DataContractSerializer
to serialize my data. And I'd like to use Protobuf
instead for performance reason.
I use a serializer to store blobs inside a database, and I want to keep the data versioning features of WCF to handle more easily data contract modifications once the project is released in the real world.
The data contracts of these blobs are not known at compile time. (A list of "extension" is specified in the config file and so the extensions register DataContracts
they know at runtime)
However it seems that the only way to tell protobuf about known type is with the [ProtoInclude]
attribute.
To be more specific, here is an example of what I want to serialize.
[DataContract]
public class Mydata
{
[DataMember(Order = 1)]
public int Saved
{
get;
set;
}
}
[DataContract]
public class Container
{
[DataMember(Order = 1)]
public object Data
{
get;
set;
}
}
With DataContractSerializer
here how I do :
[TestMethod]
public void SerializeWithDataContractSerializer()
{
var container = new Container()
{
Data = new Mydata()
{
Saved = 1
}
};
DataContractSerializer serializer = new DataContractSerializer(typeof(Container), new[] { typeof(Mydata) });
var ms = new MemoryStream();
serializer.WriteObject(ms, container);
ms.Position = 0;
var containerSerialized = (Container)serializer.ReadObject(ms);
Assert.AreEqual(((Mydata)container.Data).Saved, ((Mydata)containerSerialized.Data).Saved);
}
With protobuf
here how I wanted to do (but not possible Serializer.CreateFormatter<T>()
does not take a knownTypes
parameter) :
[TestMethod]
public void SerializeWithProtoBuf()
{
var container = new Container()
{
Data = new Mydata()
{
Saved = 1
}
};
var formatter = Serializer.CreateFormatter<Container>(new[] { typeof(Mydata) });
var ms = new MemoryStream();
formatter.Serialize(ms, container);
ms.Position = 0;
var containerSerialized = (Container)formatter.Deserialize(ms);
Assert.AreEqual(((Mydata)container.Data).Saved, ((Mydata)containerSerialized.Data).Saved);
}
Any solution ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于您要序列化 root 对象,因此在 v1(完全发布的 dll)中,您可以使用 Serializer.NonGeneric.SerializeWithLengthPrefix 和 DeserializeWithLengthPrefix API 来执行此操作,特别是对每个对象使用不同的字段号(标记) -type 序列化时,并使用接受类型解析器的反序列化重载将 irks-number 转换回类型。我目前不在电脑旁,但我可以稍后添加您需要的示例。
在“v2”中,这里有其他选项:
object
,而且我仍在探索其可能的副作用(之前已将其作为一项功能请求)Since you are serialising a root object, in v1 (the fully released dll) you can do this using the Serializer.NonGeneric.SerializeWithLengthPrefix and DeserializeWithLengthPrefix API, in particular using a different field-number (tag) per-type when serialising, and using the deserialize overload that accepts a type-resolver to translate a irks-number back into a Type. I'm not at a PC currently but I can add an example later of you need.
In "v2" there are additional options here:
object
, and I am still exploring possible side-effects of this (it has been requested as a feature previously)