├── ProtoBuffer.Test ├── packages.config ├── Containers.cs ├── Properties │ └── AssemblyInfo.cs ├── SimpleSerializer_Test.cs ├── SimpleDeserializer_Test.cs └── ProtoBuffer.Test.csproj ├── ProtoBuffer ├── packages.config ├── ISimpleDeserializer.cs ├── ISimpleSerializer.cs ├── Properties │ └── AssemblyInfo.cs ├── ProtoBuffer.csproj ├── SimpleDeserializer.cs └── SimpleSerializer.cs ├── LICENSE.txt ├── ProtoBuffer.sln ├── .gitignore └── README.md /ProtoBuffer.Test/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ProtoBuffer/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ProtoBuffer/ISimpleDeserializer.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | 4 | namespace ProtoBuffer 5 | { 6 | public interface ISimpleDeserializer 7 | { 8 | T FromFile( 9 | string filePath, 10 | bool gzipDecompress = false); 11 | 12 | Task FromFileAsync( 13 | string filePath, 14 | bool gzipDecompress = false); 15 | 16 | T FromByteArray( 17 | byte[] value, 18 | bool gzipDecompress = false); 19 | 20 | T FromStringValue( 21 | string value, 22 | bool gzipDecompress = false); 23 | } 24 | } -------------------------------------------------------------------------------- /ProtoBuffer.Test/Containers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using ProtoBuf; 7 | 8 | namespace ProtoBuffer.Test 9 | { 10 | [ProtoContract] 11 | class Address 12 | { 13 | [ProtoMember(1)] 14 | public string Line1 { get; set; } 15 | [ProtoMember(2)] 16 | public string Line2 { get; set; } 17 | } 18 | 19 | [ProtoContract] 20 | class Person 21 | { 22 | [ProtoMember(1)] 23 | public int Id { get; set; } 24 | 25 | [ProtoMember(2)] 26 | public string Name { get; set; } 27 | 28 | [ProtoMember(3)] 29 | public Address Address { get; set; } 30 | } 31 | } -------------------------------------------------------------------------------- /ProtoBuffer/ISimpleSerializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | 9 | namespace ProtoBuffer 10 | { 11 | public interface ISimpleSerializer 12 | { 13 | string SaveToFile( 14 | object item, 15 | string filePath, 16 | FileMode fileMode = FileMode.Create, 17 | bool gzipCompress = false); 18 | 19 | Task SaveToFileAsync( 20 | object item, 21 | string filePath, 22 | FileMode fileMode = FileMode.Create, 23 | bool gzipCompress = false); 24 | 25 | byte[] ToByteArray( 26 | object item, 27 | bool gzipCompress = false); 28 | 29 | string ToStringValue( 30 | object item, 31 | bool gzipCompress = false); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Erik Bergstedt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /ProtoBuffer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ProtoBuffer")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ProtoBuffer")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("2d4b1f1a-373e-4b68-a1bc-28de222ae185")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /ProtoBuffer.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ProtoBuffer.Test")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ProtoBuffer.Test")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("1755b4cf-60fb-47d4-9bd9-ea9c8e60484d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /ProtoBuffer.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProtoBuffer", "ProtoBuffer\ProtoBuffer.csproj", "{2D4B1F1A-373E-4B68-A1BC-28DE222AE185}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProtoBuffer.Test", "ProtoBuffer.Test\ProtoBuffer.Test.csproj", "{1755B4CF-60FB-47D4-9BD9-EA9C8E60484D}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {2D4B1F1A-373E-4B68-A1BC-28DE222AE185}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {2D4B1F1A-373E-4B68-A1BC-28DE222AE185}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {2D4B1F1A-373E-4B68-A1BC-28DE222AE185}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {2D4B1F1A-373E-4B68-A1BC-28DE222AE185}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {1755B4CF-60FB-47D4-9BD9-EA9C8E60484D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {1755B4CF-60FB-47D4-9BD9-EA9C8E60484D}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {1755B4CF-60FB-47D4-9BD9-EA9C8E60484D}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {1755B4CF-60FB-47D4-9BD9-EA9C8E60484D}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /ProtoBuffer.Test/SimpleSerializer_Test.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Security.Cryptography; 4 | using System.Threading.Tasks; 5 | using NUnit.Framework; 6 | using ProtoBuf; 7 | using System.Xml; 8 | 9 | namespace ProtoBuffer.Test 10 | { 11 | [TestFixture] 12 | public class SimpleSerializer_Test 13 | { 14 | private readonly ISimpleSerializer _simpleSerializer; 15 | 16 | public SimpleSerializer_Test() : this(new SimpleSerializer()) 17 | { 18 | 19 | } 20 | 21 | public SimpleSerializer_Test(ISimpleSerializer simpleSerializer) 22 | { 23 | _simpleSerializer = simpleSerializer; 24 | } 25 | 26 | private Person GetObjectWithProtobufContract() 27 | { 28 | return new Person 29 | { 30 | Id = 12345, 31 | Name = "Fred", 32 | Address = new Address 33 | { 34 | Line1 = "Flat 1", 35 | Line2 = "The Meadows" 36 | } 37 | }; 38 | } 39 | 40 | 41 | [TestCase(false)] 42 | [TestCase(true)] 43 | public void Given_an_object_Then_get_its_byte_protobuf_serialize(bool useGzip) 44 | { 45 | byte[] serialized = _simpleSerializer.ToByteArray(GetObjectWithProtobufContract(), gzipCompress: useGzip); 46 | 47 | Assert.NotNull(serialized); 48 | } 49 | 50 | [TestCase(false)] 51 | [TestCase(true)] 52 | public void Given_an_object_Then_get_its_string_protobuf_serialize(bool useGzip) 53 | { 54 | string serialized = _simpleSerializer.ToStringValue(GetObjectWithProtobufContract(), gzipCompress: useGzip); 55 | 56 | Assert.NotNull(serialized); 57 | } 58 | 59 | 60 | [TestCase(false)] 61 | [TestCase(true)] 62 | public void Given_an_object_Then_get_its_protobuf_serialization_in_file(bool useGzip) 63 | { 64 | string path = "ob5.bin"; 65 | 66 | _simpleSerializer.SaveToFile(GetObjectWithProtobufContract(), path, gzipCompress: useGzip); 67 | 68 | var readAllText = File.ReadAllText(path); 69 | 70 | Assert.NotNull(readAllText); 71 | } 72 | 73 | [TestCase(false)] 74 | [TestCase(true)] 75 | public async Task Given_an_object_Then_get_its_protobuf_serialization_in_file_async(bool useGzip) 76 | { 77 | string path = "ob4.bin"; 78 | 79 | await _simpleSerializer.SaveToFileAsync(GetObjectWithProtobufContract(), path, gzipCompress: useGzip); 80 | 81 | var readAllText = File.ReadAllText(path); 82 | 83 | Assert.NotNull(readAllText); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /ProtoBuffer/ProtoBuffer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {2D4B1F1A-373E-4B68-A1BC-28DE222AE185} 8 | Library 9 | Properties 10 | ProtoBuffer 11 | ProtoBuffer 12 | v4.6 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | ..\packages\protobuf-net.2.0.0.668\lib\net40\protobuf-net.dll 36 | True 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 65 | -------------------------------------------------------------------------------- /ProtoBuffer.Test/SimpleDeserializer_Test.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using NUnit.Framework; 8 | 9 | namespace ProtoBuffer.Test 10 | { 11 | [TestFixture] 12 | public class SimpleDeserializer_Test 13 | { 14 | private readonly ISimpleSerializer _simpleSerializer; 15 | private readonly ISimpleDeserializer _simpleDeserializer; 16 | 17 | public SimpleDeserializer_Test() : this(new SimpleSerializer(), new SimpleDeserializer()) 18 | { 19 | 20 | } 21 | 22 | public SimpleDeserializer_Test(ISimpleSerializer simpleSerializer, ISimpleDeserializer simpleDeserializer) 23 | { 24 | _simpleSerializer = simpleSerializer; 25 | _simpleDeserializer = simpleDeserializer; 26 | } 27 | 28 | 29 | private Person GetObjectWithProtobufContract() 30 | { 31 | return new Person 32 | { 33 | Id = 12345, 34 | Name = "Fred", 35 | Address = new Address 36 | { 37 | Line1 = "Flat 1", 38 | Line2 = "The Meadows" 39 | } 40 | }; 41 | } 42 | 43 | [TestCase(false)] 44 | [TestCase(true)] 45 | public void Given_an_object_Then_protobuf_serialize_and_deseserialize_with_byte(bool useGzip) 46 | { 47 | var serialize = _simpleSerializer.ToStringValue(GetObjectWithProtobufContract(), gzipCompress: useGzip); 48 | 49 | Person deserialize = _simpleDeserializer.FromStringValue(serialize, gzipDecompress: useGzip); 50 | 51 | Assert.NotNull(deserialize); 52 | } 53 | 54 | [TestCase(false)] 55 | [TestCase(true)] 56 | public void Given_an_object_Then_protobuf_serialize_and_deseserialize_with_string(bool useGzip) 57 | { 58 | var serialize = _simpleSerializer.ToByteArray(GetObjectWithProtobufContract(), gzipCompress: useGzip); 59 | 60 | Person deserialize = _simpleDeserializer.FromByteArray(serialize, gzipDecompress: useGzip); 61 | 62 | Assert.NotNull(deserialize); 63 | } 64 | 65 | [TestCase(false)] 66 | [TestCase(true)] 67 | public void Given_an_object_Then_get_its_protobuf_serialization_in_file_Then_deserialize_it(bool useGzip) 68 | { 69 | string path = "ob1.bin"; 70 | 71 | var objectWithProtobufContract = GetObjectWithProtobufContract(); 72 | 73 | _simpleSerializer.SaveToFile(objectWithProtobufContract, path, gzipCompress: useGzip); 74 | 75 | Person person = _simpleDeserializer.FromFile(path, gzipDecompress: useGzip); 76 | 77 | Assert.True(person.Id == objectWithProtobufContract.Id); 78 | } 79 | 80 | [TestCase(false)] 81 | [TestCase(true)] 82 | public async Task Given_an_object_Then_get_its_protobuf_serialization_file_Then_deserialize_it_async(bool useGzip) 83 | { 84 | string path = "ob2.bin"; 85 | 86 | var objectWithProtobufContract = GetObjectWithProtobufContract(); 87 | 88 | await _simpleSerializer.SaveToFileAsync(objectWithProtobufContract, path, gzipCompress: useGzip); 89 | 90 | Person person = await _simpleDeserializer.FromFileAsync(path, gzipDecompress: useGzip); 91 | 92 | Assert.True(person.Id == objectWithProtobufContract.Id); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /ProtoBuffer/SimpleDeserializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.IO.Compression; 4 | using System.Threading.Tasks; 5 | 6 | using ProtoBuf; 7 | 8 | namespace ProtoBuffer 9 | { 10 | public class SimpleDeserializer : ISimpleDeserializer 11 | { 12 | /// 13 | /// Deserializes from file 14 | /// 15 | /// Type to deserialize into 16 | /// Filepath for deserialization 17 | /// Use gzip decompression, if your data is serialized with gzip 18 | /// File deserialized into type 19 | public T FromFile( 20 | string filePath, 21 | bool gzipDecompress = false) 22 | { 23 | if (filePath == null) throw new ArgumentNullException(nameof(filePath)); 24 | 25 | var readAllBytes = File.ReadAllBytes(filePath); 26 | 27 | return FromByteArray(readAllBytes, gzipDecompress); 28 | } 29 | 30 | /// 31 | /// Deserializes from file 32 | /// 33 | /// Type to deserialize into 34 | /// Filepath for deserialization 35 | /// Use gzip decompression, if your data is serialized with gzip 36 | /// File deserialized into type 37 | public async Task FromFileAsync( 38 | string filePath, 39 | bool gzipDecompress = false) 40 | { 41 | if (filePath == null) throw new ArgumentNullException(nameof(filePath)); 42 | 43 | 44 | using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.Asynchronous)) 45 | { 46 | byte[] buff = new byte[fs.Length]; 47 | await fs.ReadAsync(buff, 0, (int)fs.Length); 48 | fs.Position = 0; 49 | 50 | if (gzipDecompress) 51 | { 52 | using (var gzip = new GZipStream(fs, CompressionMode.Decompress, true)) 53 | { 54 | return Serializer.Deserialize(gzip); 55 | } 56 | } 57 | 58 | return Serializer.Deserialize(fs); 59 | } 60 | } 61 | 62 | /// 63 | /// Deserializes from byte array 64 | /// 65 | /// Type to deserialize into 66 | /// Byte-array to be deserialized 67 | /// Use gzip decompression, if your data is serialized with gzip 68 | /// Byte-array deserialized into type 69 | public T FromByteArray( 70 | byte[] value, 71 | bool gzipDecompress = false) 72 | { 73 | if (value == null) throw new ArgumentNullException(nameof(value)); 74 | 75 | using (var ms = new MemoryStream(value)) 76 | { 77 | if (gzipDecompress) 78 | { 79 | using (var gzip = new GZipStream(ms, CompressionMode.Decompress, true)) 80 | { 81 | return Serializer.Deserialize(gzip); 82 | } 83 | } 84 | 85 | return Serializer.Deserialize(ms); 86 | } 87 | } 88 | 89 | public T FromStringValue( 90 | string value, 91 | bool gzipDecompress = false) 92 | { 93 | if (string.IsNullOrEmpty(value)) throw new ArgumentNullException(nameof(value)); 94 | 95 | return FromByteArray( 96 | Convert.FromBase64String(value), 97 | gzipDecompress); 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /ProtoBuffer/SimpleSerializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.IO.Compression; 4 | using System.Threading.Tasks; 5 | 6 | using ProtoBuf; 7 | 8 | namespace ProtoBuffer 9 | { 10 | public class SimpleSerializer : ISimpleSerializer 11 | { 12 | private const int GZIP_BUFFER_SIZE = 64*1024; 13 | 14 | /// 15 | /// Saves item to file 16 | /// 17 | /// Item to be saved 18 | /// Destination filepath 19 | /// 20 | /// Use gzip compression 21 | /// Saved filepath 22 | public string SaveToFile( 23 | object item, 24 | string filePath, 25 | FileMode fileMode = FileMode.Create, 26 | bool gzipCompress = false) 27 | { 28 | if (item == null) throw new ArgumentNullException(nameof(item)); 29 | if (filePath == null) throw new ArgumentNullException(nameof(filePath)); 30 | 31 | if (!filePath.EndsWith(".bin")) 32 | throw new ArgumentException("filePath must end with .bin"); 33 | 34 | var byteArray = ToByteArray(item, gzipCompress); 35 | 36 | File.WriteAllBytes(filePath, byteArray); 37 | 38 | return filePath; 39 | } 40 | 41 | /// 42 | /// Saves item to file 43 | /// 44 | /// Item to be saved 45 | /// Destination filepath 46 | /// 47 | /// Use gzip compression 48 | /// Saved filepath 49 | public async Task SaveToFileAsync( 50 | object item, 51 | string filePath, 52 | FileMode fileMode = FileMode.Create, 53 | bool gzipCompress = false) 54 | { 55 | if (item == null) throw new ArgumentNullException(nameof(item)); 56 | if (filePath == null) throw new ArgumentNullException(nameof(filePath)); 57 | 58 | if (!filePath.EndsWith(".bin")) 59 | throw new ArgumentException("filePath must end with .bin"); 60 | 61 | var byteArray = ToByteArray(item, gzipCompress); 62 | 63 | using (var fs = new FileStream(filePath, fileMode)) 64 | { 65 | await fs.WriteAsync(byteArray, 0, byteArray.Length); 66 | } 67 | 68 | return filePath; 69 | } 70 | 71 | /// 72 | /// Transforms item to protobuf byte array 73 | /// 74 | /// Item to be serialized 75 | /// Use gzip compression 76 | /// String serialization of the item 77 | public byte[] ToByteArray( 78 | object item, 79 | bool gzipCompress = false) 80 | { 81 | if (item == null) throw new ArgumentNullException(nameof(item)); 82 | 83 | using (var ms = new MemoryStream()) 84 | { 85 | if (gzipCompress) 86 | { 87 | using (var gzip = new GZipStream(ms, CompressionMode.Compress, true)) 88 | using (var bs = new BufferedStream(gzip, GZIP_BUFFER_SIZE)) 89 | { 90 | Serializer.Serialize(bs, item); 91 | } //flush gzip 92 | } 93 | else 94 | { 95 | Serializer.Serialize(ms, item); 96 | } 97 | 98 | return ms.ToArray(); 99 | } 100 | } 101 | 102 | public string ToStringValue( 103 | object item, 104 | bool gzipCompress = false) 105 | { 106 | return Convert.ToBase64String( 107 | ToByteArray(item, 108 | gzipCompress)); 109 | } 110 | } 111 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | 84 | # Visual Studio profiler 85 | *.psess 86 | *.vsp 87 | *.vspx 88 | *.sap 89 | 90 | # TFS 2012 Local Workspace 91 | $tf/ 92 | 93 | # Guidance Automation Toolkit 94 | *.gpState 95 | 96 | # ReSharper is a .NET coding add-in 97 | _ReSharper*/ 98 | *.[Rr]e[Ss]harper 99 | *.DotSettings.user 100 | 101 | # JustCode is a .NET coding add-in 102 | .JustCode 103 | 104 | # TeamCity is a build add-in 105 | _TeamCity* 106 | 107 | # DotCover is a Code Coverage Tool 108 | *.dotCover 109 | 110 | # NCrunch 111 | _NCrunch_* 112 | .*crunch*.local.xml 113 | nCrunchTemp_* 114 | 115 | # MightyMoose 116 | *.mm.* 117 | AutoTest.Net/ 118 | 119 | # Web workbench (sass) 120 | .sass-cache/ 121 | 122 | # Installshield output folder 123 | [Ee]xpress/ 124 | 125 | # DocProject is a documentation generator add-in 126 | DocProject/buildhelp/ 127 | DocProject/Help/*.HxT 128 | DocProject/Help/*.HxC 129 | DocProject/Help/*.hhc 130 | DocProject/Help/*.hhk 131 | DocProject/Help/*.hhp 132 | DocProject/Help/Html2 133 | DocProject/Help/html 134 | 135 | # Click-Once directory 136 | publish/ 137 | 138 | # Publish Web Output 139 | *.[Pp]ublish.xml 140 | *.azurePubxml 141 | # TODO: Comment the next line if you want to checkin your web deploy settings 142 | # but database connection strings (with potential passwords) will be unencrypted 143 | *.pubxml 144 | *.publishproj 145 | 146 | # NuGet Packages 147 | *.nupkg 148 | # The packages folder can be ignored because of Package Restore 149 | **/packages/* 150 | # except build/, which is used as an MSBuild target. 151 | !**/packages/build/ 152 | # Uncomment if necessary however generally it will be regenerated when needed 153 | #!**/packages/repositories.config 154 | # NuGet v3's project.json files produces more ignoreable files 155 | *.nuget.props 156 | *.nuget.targets 157 | 158 | # Microsoft Azure Build Output 159 | csx/ 160 | *.build.csdef 161 | 162 | # Microsoft Azure Emulator 163 | ecf/ 164 | rcf/ 165 | 166 | # Windows Store app package directories and files 167 | AppPackages/ 168 | BundleArtifacts/ 169 | Package.StoreAssociation.xml 170 | _pkginfo.txt 171 | 172 | # Visual Studio cache files 173 | # files ending in .cache can be ignored 174 | *.[Cc]ache 175 | # but keep track of directories ending in .cache 176 | !*.[Cc]ache/ 177 | 178 | # Others 179 | ClientBin/ 180 | ~$* 181 | *~ 182 | *.dbmdl 183 | *.dbproj.schemaview 184 | *.pfx 185 | *.publishsettings 186 | node_modules/ 187 | orleans.codegen.cs 188 | 189 | # Since there are multiple workflows, uncomment next line to ignore bower_components 190 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 191 | #bower_components/ 192 | 193 | # RIA/Silverlight projects 194 | Generated_Code/ 195 | 196 | # Backup & report files from converting an old project file 197 | # to a newer Visual Studio version. Backup files are not needed, 198 | # because we have git ;-) 199 | _UpgradeReport_Files/ 200 | Backup*/ 201 | UpgradeLog*.XML 202 | UpgradeLog*.htm 203 | 204 | # SQL Server files 205 | *.mdf 206 | *.ldf 207 | 208 | # Business Intelligence projects 209 | *.rdl.data 210 | *.bim.layout 211 | *.bim_*.settings 212 | 213 | # Microsoft Fakes 214 | FakesAssemblies/ 215 | 216 | # GhostDoc plugin setting file 217 | *.GhostDoc.xml 218 | 219 | # Node.js Tools for Visual Studio 220 | .ntvs_analysis.dat 221 | 222 | # Visual Studio 6 build log 223 | *.plg 224 | 225 | # Visual Studio 6 workspace options file 226 | *.opt 227 | 228 | # Visual Studio LightSwitch build output 229 | **/*.HTMLClient/GeneratedArtifacts 230 | **/*.DesktopClient/GeneratedArtifacts 231 | **/*.DesktopClient/ModelManifest.xml 232 | **/*.Server/GeneratedArtifacts 233 | **/*.Server/ModelManifest.xml 234 | _Pvt_Extensions 235 | 236 | # Paket dependency manager 237 | .paket/paket.exe 238 | 239 | # FAKE - F# Make 240 | .fake/ 241 | 242 | # JetBrains Rider 243 | .idea/ 244 | *.sln.iml 245 | -------------------------------------------------------------------------------- /ProtoBuffer.Test/ProtoBuffer.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {1755B4CF-60FB-47D4-9BD9-EA9C8E60484D} 7 | Library 8 | Properties 9 | ProtoBuffer.Test 10 | ProtoBuffer.Test 11 | v4.6 12 | 512 13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 10.0 15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages 17 | False 18 | UnitTest 19 | 20 | 21 | 22 | true 23 | full 24 | false 25 | bin\Debug\ 26 | DEBUG;TRACE 27 | prompt 28 | 4 29 | 30 | 31 | pdbonly 32 | true 33 | bin\Release\ 34 | TRACE 35 | prompt 36 | 4 37 | 38 | 39 | 40 | ..\packages\NUnit.2.6.4\lib\nunit.framework.dll 41 | True 42 | 43 | 44 | ..\packages\protobuf-net.2.0.0.668\lib\net40\protobuf-net.dll 45 | True 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | {2d4b1f1a-373e-4b68-a1bc-28de222ae185} 70 | ProtoBuffer 71 | 72 | 73 | 74 | 75 | 76 | 77 | False 78 | 79 | 80 | False 81 | 82 | 83 | False 84 | 85 | 86 | False 87 | 88 | 89 | 90 | 91 | 92 | 93 | 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ProtoBuffer 2 | 3 | A simple wrapper library for **[protobuf-net](https://github.com/mgravell/protobuf-net)** with async, gzip and 4 | less boilerplate. 5 | 6 | **ProtoBuffer** will remove some repetitive code declarations, like streams initializations and reading. It supports object to byte array or to file, with serialization and deserialization. It can also employ **gzip**. Just remember to keep track on which objects are gzipped or not when you deserialize them. 7 | 8 | **[Performance report](https://github.com/sidshetye/SerializersCompare)** for ProtoBuf shows that it's one of the fastest serializers for C#. But what ProtoBuf is designed for is unprecedented speed of deserialization, with a very compact format. This makes it a prime candidate for your caching solution, such as using Redis together with ProtoBuf for extremely fast data transfer and deserialization. This is as of 2016 the solution deployed in production at Stack Overflow. 9 | 10 | # Usage 11 | 12 | The test files are self-explanatory. Click below to go to the test files. 13 | 14 | **[Protobuffer.SimpleSerializer](https://github.com/ebergstedt/ProtoBuffer/blob/master/ProtoBuffer.Test/SimpleSerializer_Test.cs)** helps with serialization. 15 | 16 | **[Protobuffer.SimpleDeserializer](https://github.com/ebergstedt/ProtoBuffer/blob/master/ProtoBuffer.Test/SimpleDeserializer_Test.cs)** helps with deserialization. 17 | 18 | Here is a sample: 19 | 20 | ```C# 21 | [TestCase(false)] 22 | [TestCase(true)] 23 | public void Given_an_object_Then_protobuf_serialize_and_deseserialize_with_byte(bool useGzip) 24 | { 25 | var serialize = _simpleSerializer.ToStringValue(GetObjectWithProtobufContract(), gzipCompress: useGzip); 26 | 27 | Person deserialize = _simpleDeserializer.FromStringValue(serialize, gzipDecompress: useGzip); 28 | 29 | Assert.NotNull(deserialize); // True !! 30 | } 31 | ``` 32 | 33 | # Methods 34 | 35 | ## Protobuffer.SimpleSerializer 36 | ```C# 37 | string SaveToFile( 38 | object item, 39 | string filePath, 40 | FileMode fileMode = FileMode.Create, 41 | bool gzipCompress = false); 42 | 43 | Task SaveToFileAsync( 44 | object item, 45 | string filePath, 46 | FileMode fileMode = FileMode.Create, 47 | bool gzipCompress = false); 48 | 49 | byte[] ToByteArray( 50 | object item, 51 | bool gzipCompress = false); 52 | 53 | string ToStringValue( 54 | object item, 55 | bool gzipCompress = false); 56 | ``` 57 | 58 | ## Protobuffer.SimpleDeserializer 59 | ```C# 60 | T FromFile( 61 | string filePath, 62 | bool gzipDecompress = false); 63 | 64 | Task FromFileAsync( 65 | string filePath, 66 | bool gzipDecompress = false); 67 | 68 | T FromByteArray( 69 | byte[] value, 70 | bool gzipDecompress = false); 71 | 72 | T FromStringValue( 73 | string value, 74 | bool gzipDecompress = false); 75 | ``` 76 | 77 | # Gzip? 78 | In ProtoBuffer you may chose to employ Gzip. Your data can be Gzipped before it's serialized into the ProtoBuf format. 79 | 80 | Gzip's purpose is primarily used to compress strings. That is why it's the preferred serialization format for webservers to serve html/javascript/css which are in a string format. If your data contains a lot of strings, then you may see a considerable size compression when using Gzip. Be aware though that Gzip can increase the size of your data should it not contain enough strings. 81 | 82 | # Helpful links 83 | 84 | **[Protobuf-net: the unofficial manual](http://www.codeproject.com/Articles/642677/Protobuf-net-the-unofficial-manual)** 85 | 86 | **[Google ProtoBuf documentation](https://developers.google.com/protocol-buffers/docs/overview)** 87 | 88 | **[ProtoBuf vs Json vs XML](http://stackoverflow.com/questions/14028293/google-protocol-buffers-vs-json-vs-xml)** 89 | 90 | 91 | # Contributors 92 | 93 | [ebergstedt](https://github.com/ebergstedt) 94 | [eridleyj](https://github.com/eridleyj) 95 | 96 | # Contributing 97 | 98 | **Getting started with Git and GitHub** 99 | 100 | * **[Setting up Git for Windows and connecting to GitHub](https://help.github.com/articles/set-up-git/)** 101 | * **[Forking a GitHub repository](https://help.github.com/articles/fork-a-repo/)** 102 | * **[The simple guide to GIT guide](http://rogerdudler.github.io/git-guide/)** 103 | * **[Open an issue](https://github.com/ebergstedt/ProtoBuffer/issues)** if you encounter a bug or have a suggestion for improvements/features 104 | Once you're familiar with Git and GitHub, clone the repository and start contributing. 105 | 106 | 107 | 108 | # License 109 | 110 | The MIT License (MIT) 111 | 112 | Copyright (c) 2016 Erik Bergstedt 113 | 114 | Permission is hereby granted, free of charge, to any person obtaining a copy 115 | of this software and associated documentation files (the "Software"), to deal 116 | in the Software without restriction, including without limitation the rights 117 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 118 | copies of the Software, and to permit persons to whom the Software is 119 | furnished to do so, subject to the following conditions: 120 | 121 | The above copyright notice and this permission notice shall be included in all 122 | copies or substantial portions of the Software. 123 | 124 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 125 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 126 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 127 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 128 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 129 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 130 | SOFTWARE. --------------------------------------------------------------------------------