1

So, I want to implement my own binary serialization. I'm looking for some examples to head me in the right direction.

Also, am I better to make my own serializer class, or just implement ISerializable and use BinarySerializer? If I implement Iserializable, does that get around the assembly loading/version dependency problems with BinarySerializer?

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
Kratz
  • 4,280
  • 3
  • 32
  • 55
  • 3
    What's the reason for a custom binary serializer? – Tomas McGuinness Apr 14 '11 at 15:42
  • +1 for tomas. I could see building a custom XML serializer if you needed the XML to look a very specific way, but for binary? Are you trying to interface with some existing API where there are objects represented as binary data? Need some more info here – DarinH Apr 14 '11 at 15:46
  • Part of the application is running as a Add-In for AutoCAD. In that situation, deserialization always fails, claming that it can't find an assembly. I know the assembly is there cause code from that assemlby has to run before it gets to this point. Partially curiosity as well(i like to learn new stuff). – Kratz Apr 14 '11 at 15:49
  • @drventure, its also a performance thing. I have a custom XML serializer already, but It can take 20 seconds to run while the user is waiting for it. – Kratz Apr 14 '11 at 15:50
  • as a side note, you can fixup assembly load failures using the AssemblyLoad event. Personally I'd agree with @wal, but I'm kinda biased – Marc Gravell Apr 14 '11 at 16:09

2 Answers2

2

Check out protobuf-net written by Marc Gravell (a Stack Overflow guy)

I would avoid implementing your own, unless you have to of course. The project is open source so you can check it out.

I now use this after getting fed up with BinaryFormatter

Using protobuf is easy and its ultra fast, and it does NOT experience the assembly loading/version dependency problems.

Oh and if you need some performance stats, check this out. Fast!

I asked a similar question about an alternative to BinaryFormatter

Community
  • 1
  • 1
wal
  • 17,409
  • 8
  • 74
  • 109
  • Saved me some typing :) actually, in many ways the "v1" code and the "v2" code show 2 different ways of doing this - the rewrite is quite brutal internally. V1 is available as a "nuget" package inside VS2010. – Marc Gravell Apr 14 '11 at 16:07
  • speaking of v2...hows it looking? – wal Apr 14 '11 at 16:09
  • Gave it a shot, but you have to mark all the fields to be serialized. Its not just a lot of data I have, but a very deep structure with many classes. It sounds like v2 would work around that problem, but it doesn't seem to be out yet. – Kratz Apr 14 '11 at 16:56
  • This is the answer to my question, as this is an example of binary serialization. – Kratz Apr 14 '11 at 17:37
0

Here is an example in vb.net

I converted it from some c# so sorry if it doesn't compile, but will hopefully help you

I posted the c# code also.

If you need to persist the serialized object I recommend using base64 to a type ntext if you're using ms sql.....

My example serializes the whole object this or me in vb.net, however sometimes you may want to have full control or you may run into problems with the security attribute which can cause security issues - if so you can serialize individual fields and remove the serialize attribute. so I included the code to serialize individual fields - they are commented out

There are many ways to serialize objects in .NET, sometimes the attribute Serialize can cause security issues then you have to serialize each field.

Imports System.Linq
Imports System.Collections.Generic
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.IO

Namespace ConsoleApp
    <Serializable> _
    Public Class Example
        Public Property S() As String
            Get
                Return m_S
            End Get
            Set
                m_S = Value
            End Set
        End Property
        Private m_S As String
        Public Property I() As Integer
            Get
                Return m_I
            End Get
            Set
                m_I = Value
            End Set
        End Property
        Private m_I As Integer
        Public Property List() As List(Of String)
            Get
                Return m_List
            End Get
            Set
                m_List = Value
            End Set
        End Property
        Private m_List As List(Of String)
        Public Function Pack() As Byte()
            Dim bf = New BinaryFormatter()
            Using ms = New MemoryStream()
                bf.Serialize(ms, Me)
                '               bf.Serialize(ms, S);
                '               bf.Serialize(ms, I);
                '               bf.Serialize(ms, List);
                Return ms.ToArray()
            End Using
        End Function
        Public Function UnPack(data As Byte()) As Example
            Dim bf = New BinaryFormatter()
            Using ms = New MemoryStream(data)
                    '               S = (string) bf.Deserialize(ms);
                    '               I = (int) bf.Deserialize(ms);
                    '               List = (List<string>) bf.Deserialize(ms);               
                Return DirectCast(bf.Deserialize(ms), Example)
            End Using
            '           return this;
        End Function
        Public Overrides Function ToString() As String
            Return String.Format("[Example: S={0}, I={1}, List={2}]", S, I, [String].Join(",", List.ToArray()))
        End Function
    End Class
    Class MainClass

        Public Shared Sub Main(args As String())

            Dim o1 = New Example() With { _
                Key .S = "James", _
                Key .I = 9, _
                Key .List = New List(Of String)(New String() {"a", "b"}) _
            }
            Dim o2 = New Example().UnPack(o1.Pack())
            Console.WriteLine(o1.ToString())
            Console.WriteLine(o2.ToString())

            Console.ReadLine()

        End Sub

    End Class
End Namespace

C# source

using System;
using System.Linq;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace ConsoleApp
{
    [Serializable()]
    public class Example {
        public string S {get;set;}
        public int I {get;set;}
        public List<string> List {get; set;}
        public byte[] Pack() {
            var bf = new BinaryFormatter();
            using (var ms = new MemoryStream()) {
                bf.Serialize(ms, this);
//              bf.Serialize(ms, S);
//              bf.Serialize(ms, I);
//              bf.Serialize(ms, List);
                return ms.ToArray();
            }
        }
        public Example UnPack(byte[] data) {
            var bf = new BinaryFormatter();
            using (var ms = new MemoryStream(data)) {
                return (Example) bf.Deserialize(ms);
//              S = (string) bf.Deserialize(ms);
//              I = (int) bf.Deserialize(ms);
//              List = (List<string>) bf.Deserialize(ms);               
            }
//          return this;
        }
        public override string ToString ()
        {
            return string.Format ("[Example: S={0}, I={1}, List={2}]", S, I, String.Join(",", List.ToArray()));
        }
    }
    class MainClass
    {

        public static void Main (string[] args)
        {

            var o1 = new Example() {S = "James", I = 9, List= new List<string>(new string[] {"a", "b"})};
            var o2 = new Example().UnPack(o1.Pack());
            Console.WriteLine(o1.ToString());
            Console.WriteLine(o2.ToString());

            Console.ReadLine();

        }

    }
}
James Kyburz
  • 13,775
  • 1
  • 32
  • 33