Note that there are some explanatory texts on larger screens.

plurals
  1. POprotobuf-net and de/serializing objects
    text
    copied!<p>I am checking if protobuf-net can be an in place replacement for DataContracts. Besides the excellent performance it is really a neat library. The only issue I have is that the .NET serializers do not make any assumptions what they are currently de/serializing. Especially objects which do contain reference to the typed object are a problem. </p> <pre><code>[DataMember(Order = 3)] public object Tag1 // The DataContract did contain a object which becomes now a SimulatedObject { get; set; } </code></pre> <p>I tried to mimic object with protocol buffers with a little generic helper which does store for each possible type in a different strongly typed field. </p> <p>Is this an recommended approach to deal with fields which de/serialize into a number of different not related types? </p> <p>Below is the sample code for a SimulatedObject which can hold up to 10 different types. </p> <pre><code>using System; using System.Collections.Generic; using System.IO; using System.Runtime.Serialization; using ProtoBuf; using System.Diagnostics; [DataContract] public class SimulatedObject&lt;T1,T2,T3,T4,T5,T6,T7,T8,T9,T10&gt; { [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&lt;bool, Other, Other, Other, Other, Other, Other, Other, Other, SomethingDifferent&gt; Tag1 // Can contain up to 10 different types { get; set; } [DataMember(Order = 4)] public List&lt;string&gt; 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&lt;string&gt; { "First", "Second", "Third" }, Tag1 = new SimulatedObject&lt;bool, Other, Other, Other, Other, Other, Other, Other, Other, SomethingDifferent&gt; { Data = new Other { OtherData = "String value "} } }; const int Runs = 1000 * 1000; var stream = new MemoryStream(); var sw = Stopwatch.StartNew(); Serializer.Serialize&lt;Customer&gt;(stream, c); sw = Stopwatch.StartNew(); for (int i = 0; i &lt; Runs; i++) { stream.Position = 0; stream.SetLength(0); Serializer.Serialize&lt;Customer&gt;(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&lt;Customer&gt;(stream); sw = Stopwatch.StartNew(); for (int i = 0; i &lt; Runs; i++) { stream.Position = 0; var newCust = Serializer.Deserialize&lt;Customer&gt;(stream); } sw.Stop(); Console.WriteLine("Read object with Protocol buffer deserializer: {0} objects did take {1}s", Runs, sw.Elapsed.TotalSeconds); } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload