C# protobuf网络和对象反序列化
我正在检查protobuf net是否可以替代DataContracts。除了出色的性能外,这真是一个整洁的图书馆。我唯一的问题是.NET序列化程序没有对当前正在反序列化的内容进行任何假设。尤其是包含对类型化对象的引用的对象是一个问题C# protobuf网络和对象反序列化,c#,.net,protobuf-net,C#,.net,Protobuf Net,我正在检查protobuf net是否可以替代DataContracts。除了出色的性能外,这真是一个整洁的图书馆。我唯一的问题是.NET序列化程序没有对当前正在反序列化的内容进行任何假设。尤其是包含对类型化对象的引用的对象是一个问题 [DataMember(Order = 3)] public object Tag1 // The DataContract did contain a object which becomes now a SimulatedObject { get;
[DataMember(Order = 3)]
public object Tag1 // The DataContract did contain a object which becomes now a SimulatedObject
{
get;
set;
}
我试着用协议缓冲区模拟对象,其中有一个小的泛型助手,它将每个可能的类型存储在不同的强类型字段中
这是处理反序列化为许多不同的不相关类型的字段的推荐方法吗
下面是一个模拟对象的示例代码,它最多可以容纳10种不同的类型
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using ProtoBuf;
using System.Diagnostics;
[DataContract]
public class SimulatedObject<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>
{
[DataMember(Order = 20)]
byte FieldHasValue; // the number indicates which field actually has a value
[DataMember(Order = 1)]
T1 I1;
[DataMember(Order = 2)]
T2 I2;
[DataMember(Order = 3)]
T3 I3;
[DataMember(Order = 4)]
T4 I4;
[DataMember(Order = 5)]
T5 I5;
[DataMember(Order = 6)]
T6 I6;
[DataMember(Order = 7)]
T7 I7;
[DataMember(Order = 8)]
T8 I8;
[DataMember(Order = 9)]
T9 I9;
[DataMember(Order = 10)]
T10 I10;
public object Data
{
get
{
switch(FieldHasValue)
{
case 0: return null;
case 1: return I1;
case 2: return I2;
case 3: return I3;
case 4: return I4;
case 5: return I5;
case 6: return I6;
case 7: return I7;
case 8: return I8;
case 9: return I9;
case 10: return I10;
default:
throw new NotSupportedException(String.Format("The FieldHasValue field has an invlaid value {0}. This indicates corrupt data or incompatible data layout chagnes", FieldHasValue));
}
}
set
{
I1 = default(T1);
I2 = default(T2);
I3 = default(T3);
I4 = default(T4);
I5 = default(T5);
I6 = default(T6);
I7 = default(T7);
I8 = default(T8);
I9 = default(T9);
I10 = default(T10);
if (value != null)
{
Type t = value.GetType();
if (t == typeof(T1))
{
FieldHasValue = 1;
I1 = (T1) value;
}
else if (t == typeof(T2))
{
FieldHasValue = 2;
I2 = (T2) value;
}
else if (t == typeof(T3))
{
FieldHasValue = 3;
I3 = (T3) value;
}
else if (t == typeof(T4))
{
FieldHasValue = 4;
I4 = (T4) value;
}
else if (t == typeof(T5))
{
FieldHasValue = 5;
I5 = (T5) value;
}
else if (t == typeof(T6))
{
FieldHasValue = 6;
I6 = (T6) value;
}
else if (t == typeof(T7))
{
FieldHasValue = 7;
I7 = (T7) value;
}
else if (t == typeof(T8))
{
FieldHasValue = 8;
I8 = (T8) value;
}
else if (t == typeof(T9))
{
FieldHasValue = 9;
I9 = (T9) value;
}
else if (t == typeof(T10))
{
FieldHasValue = 10;
I10 = (T10) value;
}
else
{
throw new NotSupportedException(String.Format("The type {0} is not supported for serialization. Please add the type to the SimulatedObject generic argument list.", t.FullName));
}
}
}
}
}
[DataContract]
class Customer
{
/*
[DataMember(Order = 3)]
public object Tag1 // The DataContract did contain a object which becomes now a SimulatedObject
{
get;
set;
}
*/
[DataMember(Order = 3)]
public SimulatedObject<bool, Other, Other, Other, Other, Other, Other, Other, Other, SomethingDifferent> Tag1 // Can contain up to 10 different types
{
get;
set;
}
[DataMember(Order = 4)]
public List<string> Strings
{
get;
set;
}
}
[DataContract]
public class Other
{
[DataMember(Order = 1)]
public string OtherData
{
get;
set;
}
}
[DataContract]
public class SomethingDifferent
{
[DataMember(Order = 1)]
public string OtherData
{
get;
set;
}
}
class Program
{
static void Main(string[] args)
{
Customer c = new Customer
{
Strings = new List<string> { "First", "Second", "Third" },
Tag1 = new SimulatedObject<bool, Other, Other, Other, Other, Other, Other, Other, Other, SomethingDifferent>
{
Data = new Other { OtherData = "String value "}
}
};
const int Runs = 1000 * 1000;
var stream = new MemoryStream();
var sw = Stopwatch.StartNew();
Serializer.Serialize<Customer>(stream, c);
sw = Stopwatch.StartNew();
for (int i = 0; i < Runs; i++)
{
stream.Position = 0;
stream.SetLength(0);
Serializer.Serialize<Customer>(stream, c);
}
sw.Stop();
Console.WriteLine("Data Size with Protocol buffer Serializer: {0}, {1} objects did take {2}s", stream.ToArray().Length, Runs, sw.Elapsed.TotalSeconds);
stream.Position = 0;
var newCustw = Serializer.Deserialize<Customer>(stream);
sw = Stopwatch.StartNew();
for (int i = 0; i < Runs; i++)
{
stream.Position = 0;
var newCust = Serializer.Deserialize<Customer>(stream);
}
sw.Stop();
Console.WriteLine("Read object with Protocol buffer deserializer: {0} objects did take {1}s", Runs, sw.Elapsed.TotalSeconds);
}
}
使用系统;
使用System.Collections.Generic;
使用System.IO;
使用System.Runtime.Serialization;
使用ProtoBuf;
使用系统诊断;
[数据合同]
公共类模拟对象
{
[数据成员(顺序=20)]
byte FieldHasValue;//该数字指示哪个字段实际有值
[数据成员(顺序=1)]
T1-I1;
[数据成员(顺序=2)]
t2i2;
[数据成员(顺序=3)]
t3i3;
[数据成员(顺序=4)]
T4 I4;
[数据成员(顺序=5)]
t5i5;
[数据成员(顺序=6)]
t6i6;
[数据成员(顺序=7)]
t7i7;
[数据成员(顺序=8)]
t8i8;
[数据成员(顺序=9)]
t9i9;
[数据成员(顺序=10)]
t10i10;
公共对象数据
{
得到
{
开关(FieldHasValue)
{
案例0:返回null;
案例1:返回I1;
案例2:返回I2;
案例3:返回I3;
案例4:返回I4;
案例5:返回I5;
案例6:返回I6;
案例7:返回I7;
案例8:返回I8;
案例9:返回I9;
案例10:返回I10;
违约:
抛出新的NotSupportedException(String.Format(“FieldHasValue字段有一个Invlaed值{0}。这表示数据损坏或数据布局不兼容”,FieldHasValue));
}
}
设置
{
I1=默认值(T1);
I2=默认值(T2);
I3=默认值(T3);
I4=违约(T4);
I5=默认值(T5);
I6=默认值(T6);
I7=默认值(T7);
I8=默认值(T8);
I9=默认值(T9);
I10=默认值(T10);
if(值!=null)
{
类型t=value.GetType();
if(t==typeof(T1))
{
FieldHasValue=1;
I1=(T1)值;
}
else if(t==typeof(T2))
{
FieldHasValue=2;
I2=(T2)值;
}
else if(t==typeof(T3))
{
FieldHasValue=3;
I3=(T3)值;
}
否则如果(t==类型(T4))
{
FieldHasValue=4;
I4=(T4)值;
}
else if(t==类型(T5))
{
FieldHasValue=5;
I5=(T5)值;
}
else if(t==typeof(T6))
{
FieldHasValue=6;
I6=(T6)值;
}
else if(t==typeof(T7))
{
FieldHasValue=7;
I7=(T7)值;
}
else if(t==typeof(T8))
{
FieldHasValue=8;
I8=(T8)值;
}
else if(t==typeof(T9))
{
FieldHasValue=9;
I9=(T9)值;
}
else if(t==typeof(T10))
{
FieldHasValue=10;
I10=(T10)值;
}
其他的
{
抛出新的NotSupportedException(String.Format(“序列化不支持类型{0}。请将该类型添加到SimulatedObject泛型参数列表。”,t.FullName));
}
}
}
}
}
[数据合同]
类客户
{
/*
[数据成员(顺序=3)]
public object Tag1//DataContract确实包含一个对象,该对象现在已成为模拟对象
{
得到;
设置
}
*/
[数据成员(顺序=3)]
公共模拟对象Tag1//最多可以包含10种不同类型
{
得到;
设置
}
[数据成员(顺序=4)]
公共列表字符串
{
得到;
设置
}
}
[数据合同]
公共类其他
{
[数据成员(顺序=1)]
公共字符串数据
{
得到;
设置
}
}
[数据合同]
公共课有些不同
{
[数据成员(顺序=1)]
公共字符串数据
{
得到;
设置
}
}
班级计划
{
静态void Main(字符串[]参数)
{
客户c=新客户
{
Strings=新列表{“第一”、“第二”、“第三”},
Tag1=新的模拟对象
{
Data=new Other{OtherData=“String value”}
}
};
const int Runs=1000*1000;
var stream=newmemoryStream();
var sw=Stopwatch.StartNew();
Serializer.Serialize(流,c);
sw=秒表。开始新();
for(int i=0;ipublic byte[] Serialize(object myObject)
{
using (var ms = new MemoryStream())
{
Type type = myObject.GetType();
var id = System.Text.ASCIIEncoding.ASCII.GetBytes(type.FullName + '|');
ms.Write(id, 0, id.Length);
Serializer.Serialize(ms, myObject);
var bytes = ms.ToArray();
return bytes;
}
}
public object Deserialize(byte[] serializedData)
{
StringBuilder sb = new StringBuilder();
using (var ms = new MemoryStream(serializedData))
{
while (true)
{
var currentChar = (char)ms.ReadByte();
if (currentChar == '|')
{
break;
}
sb.Append(currentChar);
}
string typeName = sb.ToString();
// assuming that the calling assembly contains the desired type.
// You can include aditional assembly information if necessary
Type deserializationType = Assembly.GetCallingAssembly().GetType(typeName);
MethodInfo mi = typeof(Serializer).GetMethod("Deserialize");
MethodInfo genericMethod = mi.MakeGenericMethod(new[] { deserializationType });
return genericMethod.Invoke(null, new[] { ms });
}
}