{"id":2299,"date":"2014-08-08T21:39:18","date_gmt":"2014-08-08T21:39:18","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=2299"},"modified":"2014-08-08T21:39:18","modified_gmt":"2014-08-08T21:39:18","slug":"using-protobuf-net-in-c","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/using-protobuf-net-in-c\/","title":{"rendered":"Using protobuf-net in C#"},"content":{"rendered":"<p><a href=\"https:\/\/code.google.com\/p\/protobuf-net\/\" title=\"protobuf-net\" target=\"_blank\">protobuf-net<\/a> is a .NET library around the Google Protocol Buffers. <\/p>\n<p>For information on the actual Google Protocol Buffers you can checkout the Google <a href=\"https:\/\/developers.google.com\/protocol-buffers\/\" title=\"Protocol Buffers\" target=\"_blank\">documentation<\/a>.<\/p>\n<p>To get the library via NuGet you can use <em>Install-Package protobuf-net<\/em> from the Package Manager Console or locate the same from the NuGet UI.<\/p>\n<p>To quote <a href=\"http:\/\/protobuffers.codeplex.com\/\" title=\"Implementing Google Protocol Buffers using C#\" target=\"_blank\">Implementing Google Protocol Buffers using C#<\/a>, &#8220;Protocol Buffers are not designed to handle large messages. If you are dealing in messages larger than a megabyte each, it may be time to consider an alternate strategy. Protocol Buffers are great for handling individual messages within a large data set. Usually, large data sets are really just a collection of small pieces, where each small piece may be a structured piece of data.&#8221;<\/p>\n<p>So Protocol Buffers are best used on small sets of of data, but let&#8217;s start coding and see how to use Protocol Buffers using protobuf-net.<\/p>\n<p><strong>Time to code<\/strong><\/p>\n<p>There are a couple of ways of making your classes compliant with the protobuf-net library, the first is to use attributes and the second without attributes, instead setting up the meta data yourself.<\/p>\n<p>Let&#8217;s look at an example from the protobuf-net website, a Person class which contains an Address class and other properties.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n&#x5B;ProtoContract]\r\npublic class Person \r\n{\r\n   &#x5B;ProtoMember(1)]\r\n   public int Id { get; set; }\r\n   &#x5B;ProtoMember(2)]\r\n   public string Name { get; set; }\r\n   &#x5B;ProtoMember(3)]\r\n   public Address Address { get; set;}\r\n}\r\n\r\n&#x5B;ProtoContract]\r\npublic class Address \r\n{\r\n   &#x5B;ProtoMember(1)]\r\n   public string Line1 {get;set;}\r\n   &#x5B;ProtoMember(2)]\r\n   public string Line2 {get;set;}\r\n}\r\n<\/pre>\n<p>As can be seen the classes to be serialized are marked with the ProtoContractAttribute. By default protobuf-net expects you to mark your objects with attributes but as already mentioned, you can also use classes without the attributes as we&#8217;ll see soon.<\/p>\n<p>The ProtoMemberAttribute marks each property to be serialized and should contain a unique, positive integer. These identifiers are serialized as opposed to the property name itself (for example) and thus you can change the property name but not the ProtoMemberAttribute number. Obviously, as this value is serialized the smaller the number the better, i.e. a large number will take up unnecessary space. <\/p>\n<p><strong>Serialize\/Deserialize<\/strong><\/p>\n<p>Once we&#8217;ve defined the objects we want to serialize with information to tell the serializer the id&#8217;s and data then we can actually start serializing and deserializing some data. So here goes. Assuming that we&#8217;ve created a Person object and assigned it to the variable <em>person<\/em> then we can do the following to serialize this instance of the Person object<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nusing (var fs = File.Create(&quot;test.bin&quot;))\r\n{\r\n   Serializer.Serialize(fs, person);\r\n}\r\n<\/pre>\n<p>and to deserialize we can do the following<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nPerson serlizedPerson;\r\nusing (var fs = File.OpenRead(&quot;test.bin&quot;))\r\n{\r\n   Person person = Serializer.Deserialize&lt;Person&gt;(fs);\r\n   \/\/ do something with person\r\n}\r\n<\/pre>\n<p><em>Note: Protocol Buffers is a binary serialization protocol<\/em><\/p>\n<p><strong>Now without attributes<\/strong><\/p>\n<p>As mentioned previously, we might not be able to alter the class definition or simply prefer to not use attributes, in which case we need to setup the meta data programmatically. So let&#8217;s redefine Person and Address just to be perfectly clear<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic class Person \r\n{\r\n   public int Id { get; set; }\r\n   public string Name { get; set; }\r\n   public Address Address { get; set;}\r\n}\r\n    \r\npublic class Address \r\n{\r\n   public string Line1 {get;set;}\r\n   public string Line2 {get;set;}\r\n}\r\n<\/pre>\n<p>Prior to serialization\/deserialization we would write something like<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar personMetaType = RuntimeTypeModel.Default.Add(typeof (Person), false);\r\npersonMetaType.Add(1, &quot;Id&quot;);\r\npersonMetaType.Add(2, &quot;Name&quot;);\r\npersonMetaType.Add(3, &quot;Address&quot;);\r\n\r\nvar addressMetaType = RuntimeTypeModel.Default.Add(typeof(Address), false);\r\naddressMetaType.Add(1, &quot;Line1&quot;);\r\naddressMetaType.Add(2, &quot;Line2&quot;);\r\n<\/pre>\n<p>as you can see we supply the identifier integer and then the property name. <\/p>\n<p>RuntimeTypeModel.Default is used to setup the configuration details for our types and their properties.<\/p>\n<p><strong>Inheritance<\/strong><\/p>\n<p>Like the SOAP serialization and the likes, when we derive a new class from a type we need to mark the base type with an attribute telling the serializer what types it might expect. So for example if we added the following derived types<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n&#x5B;ProtoContract]\r\npublic class Male : Person\r\n{\t\t\r\n}\r\n\r\n&#x5B;ProtoContract]\r\npublic class Female : Person\r\n{\t\r\n}\t\r\n<\/pre>\n<p>we&#8217;d need to update our Person class to look something like<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n&#x5B;ProtoContract]\r\n&#x5B;ProtoInclude(10, typeof(Male))]\r\n&#x5B;ProtoInclude(11, typeof(Female))]\r\npublic class Person \r\n{\r\n   \/\/ properties\r\n}\r\n<\/pre>\n<p><em>Note: the identifiers 10 and 11 are again unique positive integers but must be unique to the class, so for example no other ProtoIncludeAttribute or ProtoMemberAttribute within the class should have the same identifier.<\/em><\/p>\n<p>Without attributes we simply AddSubType to the <em>personMetaType<\/em> defined previous, so for example we would add the following code to our previous example of setting up the metadata<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n\/\/ previous metadata configuration\r\npersonMetaType.AddSubType(10, typeof (Male));\r\npersonMetaType.AddSubType(11, typeof(Female));\r\n\r\n\/\/ and now add the new types\r\nRuntimeTypeModel.Default.Add(typeof(Male), false);\r\nRuntimeTypeModel.Default.Add(typeof(Female), false);\r\n<\/pre>\n<p><strong>Alternative Implementations of Protocol Buffers for .NET<\/strong><\/p>\n<p><a href=\"https:\/\/code.google.com\/p\/protobuf-csharp-port\/\" title=\"protobuf-csharp-port\" target=\"_blank\">protobuf-csharp-port<\/a> is written by Jon Skeet and appears to be closer related to the Google code using .proto files to describe the messages.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>protobuf-net is a .NET library around the Google Protocol Buffers. For information on the actual Google Protocol Buffers you can checkout the Google documentation. To get the library via NuGet you can use Install-Package protobuf-net from the Package Manager Console or locate the same from the NuGet UI. To quote Implementing Google Protocol Buffers using [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3,81],"tags":[],"class_list":["post-2299","post","type-post","status-publish","format-standard","hentry","category-c","category-serialization"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/2299","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=2299"}],"version-history":[{"count":10,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/2299\/revisions"}],"predecessor-version":[{"id":2314,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/2299\/revisions\/2314"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=2299"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=2299"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=2299"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}