首先,你的序列化/反序列化方法都被破坏了;你过度报告了结果(GetBuffer()
, 没有Length
),并且您没有将任何内容写入流中进行反序列化。这是一个正确的实现(尽管您也可以使用GetBuffer()
如果你要回来ArraySegment<byte>
):
public static byte[] SerProtoBuf(object thisObj)
{
using (MemoryStream ms = new MemoryStream())
{
Serializer.NonGeneric.Serialize(ms, thisObj);
return ms.ToArray();
}
}
public static T DeserProtoBuf<T>(byte[] bytes)
{
using (MemoryStream ms = new MemoryStream(bytes))
{
return Serializer.Deserialize<T>(ms);
}
}
这就是为什么您没有收到任何数据的原因。其次,您没有说明如何计时,因此这是我根据您的代码编写的一些代码(其中还包括显示它正在获取所有值的代码)。结果先:
Via BinaryFormatter:
1 Disney Street
Disneyland, CA
1
FunctionNameHere
Mickey Mouse
x=1,y=2,z=3
1.2
Via protobuf-net:
1 Disney Street
Disneyland, CA
1
FunctionNameHere
Mickey Mouse
x=1,y=2,z=3
1.2
Serialize BinaryFormatter: 112 ms, 434 bytes
Deserialize BinaryFormatter: 113 ms
Serialize protobuf-net: 14 ms, 85 bytes
Deserialize protobuf-net: 19 ms
分析:
两个序列化器存储相同的数据; protobuf-net 的速度快了一个数量级,但输出却小了 5 倍。我宣布:获胜者。
Code:
static BinaryFormatter bf = new BinaryFormatter();
public static byte[] SerBinaryFormatter(object thisObj)
{
using (MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, thisObj);
return ms.ToArray();
}
}
public static T DeserBinaryFormatter<T>(byte[] bytes)
{
using (MemoryStream ms = new MemoryStream(bytes))
{
return (T)bf.Deserialize(ms);
}
}
static void Main()
{
SimpleEntity obj = new SimpleEntity(), clone;
obj.FillDummyData();
// test that we get non-zero bytes
var data = SerBinaryFormatter(obj);
clone = DeserBinaryFormatter<SimpleEntity>(data);
Console.WriteLine("Via BinaryFormatter:");
Console.WriteLine(clone.addressLine1);
Console.WriteLine(clone.addressLine2);
Console.WriteLine(clone.employeeId);
Console.WriteLine(clone.functionCall);
Console.WriteLine(clone.name);
Console.WriteLine(clone.parameters);
Console.WriteLine(clone.raiseRate);
Console.WriteLine();
data = SerProtoBuf(obj);
clone = DeserProtoBuf<SimpleEntity>(data);
Console.WriteLine("Via protobuf-net:");
Console.WriteLine(clone.addressLine1);
Console.WriteLine(clone.addressLine2);
Console.WriteLine(clone.employeeId);
Console.WriteLine(clone.functionCall);
Console.WriteLine(clone.name);
Console.WriteLine(clone.parameters);
Console.WriteLine(clone.raiseRate);
Console.WriteLine();
Stopwatch watch = new Stopwatch();
const int LOOP = 10000;
watch.Reset();
watch.Start();
for (int i = 0; i < LOOP; i++)
{
data = SerBinaryFormatter(obj);
}
watch.Stop();
Console.WriteLine("Serialize BinaryFormatter: {0} ms, {1} bytes", watch.ElapsedMilliseconds, data.Length);
watch.Reset();
watch.Start();
for (int i = 0; i < LOOP; i++)
{
clone = DeserBinaryFormatter<SimpleEntity>(data);
}
watch.Stop();
Console.WriteLine("Deserialize BinaryFormatter: {0} ms", watch.ElapsedMilliseconds, data.Length);
watch.Reset();
watch.Start();
for (int i = 0; i < LOOP; i++)
{
data = SerProtoBuf(obj);
}
watch.Stop();
Console.WriteLine("Serialize protobuf-net: {0} ms, {1} bytes", watch.ElapsedMilliseconds, data.Length);
watch.Reset();
watch.Start();
for (int i = 0; i < LOOP; i++)
{
clone = DeserProtoBuf<SimpleEntity>(data);
}
watch.Stop();
Console.WriteLine("Deserialize protobuf-net: {0} ms", watch.ElapsedMilliseconds, data.Length);
}
Lastly, [DataMember(...)]
support 并不是真正的“较新的‘统一’支持约定”——它当然不是“较新的”——我很确定它自从提交#4(可能更早)之类的东西以来就支持这两者。这只是为了方便而提供的选项:
- 并非所有目标平台都有
DataMemberAttribute
- 有些人喜欢将 DTO 层限制为内置标记
- 有些类型很大程度上超出了您的控制范围,但可能已经具有这些标记(例如,从 LINQ-to-SQL 生成的数据)
- 另外,请注意,2.x 允许您在运行时定义模型,而无需添加属性(尽管属性仍然是最重要的)方便的方法来做到这一点)