有没有人有一个工作示例,其中protobuf-net可以用作BinaryFormatter的替代品?这甚至可能吗?
实际上我只需要一个类似于
的消息类型的序列化器public class A {
public B[] Bs { get;set; }
public C[] Cs { get;set; }
}
所有类型都在不同的程序集中定义,并具有许多属性。 是否可以选择自动生成包含所有公共属性的原型合约,对于A类和其他使用类型(B,C),所以类似
var formatter = ProtoBuf.Serializer.CreateFormatter<A>()
有效吗?
答案 0 :(得分:6)
首先,protobuf-net并不打算成为BinaryFormatter
的替代品,而且并不是100%。它的功能略有不同。
您是否满足于做一些反思?基本上,支持ImplicitFields
,但目前仅通过[ProtoContract]
提供,并且无法通过RuntimeTypeModel
方便地完成,这有点痛苦,并且在我的列表中。虽然,我应该指出,我认为隐含字段有点风险,只有当你知道DTO内部不会改变时才应该这样做!但是:要回答您的问题,您可以迭代您期望的类型,并手动将它们添加到模型中:
static void Main()
{
Prepare(typeof(A), typeof(B), typeof(C));
// if you really want to use IFormatter...
var formatter = RuntimeTypeModel.Default.CreateFormatter(typeof (A));
var obj = new A {Bs = new B[] {new B()}};
using (var ms = new MemoryStream())
{
formatter.Serialize(ms, obj);
ms.Position = 0;
var clone = formatter.Deserialize(ms);
}
}
static void Prepare(params Type[] types)
{
if(types != null) foreach(var type in types) Prepare(type);
}
static void Prepare(Type type)
{
if(type != null && !RuntimeTypeModel.Default.IsDefined(type))
{
Debug.WriteLine("Preparing: " + type.FullName);
// note this has no defined sort, so invent one
var props = type.GetProperties();
Array.Sort(props, (x, y) => string.Compare(
x.Name, y.Name, StringComparison.Ordinal));
var meta = RuntimeTypeModel.Default.Add(type, false);
int fieldNum = 1;
for(int i = 0 ; i < props.Length ; i++)
{
meta.Add(fieldNum++, props[i].Name);
}
}
}
请注意,此处使用IFormatter
完全没必要;您也可以使用RuntimeTypeModel.Default.Serialize(...)
或Serializer.Serialize<T>(...)
。
作为脚注:我会建议更多地重复定义模型。例如:
RuntimeTypeModel.Default.Add(typeof(A)).Add("Bs", "Cs");
RuntimeTypeModel.Default.Add(typeof(B)).Add("Foo");
RuntimeTypeModel.Default.Add(typeof(C)).Add("Bar", "Blap", "Blop");
答案 1 :(得分:4)
这是我使用的Prepare功能的最终版本:
static void Prepare(params Type[] types)
{
foreach (var type in types)
{
if (type != null && !RuntimeTypeModel.Default.IsDefined(type))
{
if (type.Namespace.StartsWith("System"))
return;
Debug.WriteLine("Preparing: " + type.FullName);
// note this has no defined sort, so invent one
var props = type.GetProperties();
Array.Sort(props, (x, y) => string.Compare(
x.Name, y.Name, StringComparison.Ordinal));
var meta = RuntimeTypeModel.Default.Add(type, false);
int fieldNum = 1;
for (int i = 0; i < props.Length; i++)
if (props[i].CanWrite)
{
meta.Add(fieldNum++, props[i].Name);
if (!RuntimeTypeModel.Default.IsDefined(props[i].PropertyType))
if (props[i].PropertyType.HasElementType)
Prepare(props[i].PropertyType.GetElementType()); //T[]
else if (props[i].PropertyType.IsGenericType)
Prepare(props[i].PropertyType.GetGenericArguments()); //List<T>
else
Prepare(props[i].PropertyType);
}
}
}
}
如果有人感兴趣,这是我的基准测试结果(序列化+反序列化):
BinaryFormatter 10000 messages: 2.131s 5028 bytes/msg
Json.NET Bson 10000 messages: 1.679s 1071 bytes/msg
MetSys Bson 10000 messages: 1.581s 1035 bytes/msg
Protobuf 10000 messages: 0.145s 109 bytes/msg
MsgPack 10000 messages: 0.844s 106 bytes/msg
注意:
感谢Marc的帮助和如此出色的图书馆。