Serialize and Deserialize object graph using BinaryFormatter

andrewramka picture andrewramka · Feb 16, 2013 · Viewed 11k times · Source

I'm trying to serialize my object graph to a string then deserialize it from a string. The object serializes just fine if I do this

using (var memStream = new System.IO.MemoryStream())
{
     mf.Serialize(memStream, this);
     memStream.Seek(0, 0);

     Search s;
     using (var memStrClone = new System.IO.MemoryStream())
     {
          memStream.CopyTo(memStrClone);
          memStrClone.Seek(0, 0);
          s = mf.Deserialize(memStrClone) as Search;
     }
}

The above code works but serializing to a string and trying to deserialize that same string like this

Search s;
string xml = ToString<Search>(this);
s = FromString<Search>(xml);

public static TType FromString<TType>(string input)
{
     var byteArray = Encoding.ASCII.GetBytes(input);
     using (var stream = new MemoryStream(byteArray))
     {
          var bf = new BinaryFormatter();
          return (TType)bf.Deserialize(stream);
     }
}

public static string ToString<TType>(TType data)
{
     using (var ms = new MemoryStream())
     {
          var bf = new BinaryFormatter();
          bf.Serialize(ms, data);
          return Encoding.ASCII.GetString(ms.GetBuffer());
     }
}

Throws an exception

No assembly ID for object type '1936026741 Core.Sebring.BusinessObjects.Search.Search'.

Any help is greatly appreciated. Thanks.

Answer

Jay picture Jay · Feb 16, 2013

Here is some code which will do what you want to to (I think) - but I've got to ask - why do you want to serialize to a string like that?

If the class is simple enough to serialise to a string, use an XML serializer which is much easier to deal with; if you want to serialize it out to disk, binary write it out to a file and if it is complicated and you are serializing it to transmit - consider using something like protobuf-net.

I think the crux of your problem is that you are trying to use ASCII encoding - I'm using Base64 encoding.

Anyway - here goes (I've just had a guess at your Search class!)

 class Program
{
    [Serializable]
    public class Search
    {
        public Guid ID { get; private set; }

        public Search() { }

        public Search(Guid id)
        {
            ID = id;
        }

        public override string ToString()
        {
            return ID.ToString();
        }
    }

    static void Main(string[] args)
    {
        Search search = new Search(Guid.NewGuid());
        Console.WriteLine(search);
        string serialized = SerializeTest.SerializeToString(search);
        Search rehydrated = SerializeTest.DeSerializeFromString<Search>(serialized);
        Console.WriteLine(rehydrated);

        Console.ReadLine();
    }
}

public class SerializeTest
{
    public static Encoding _Encoding = Encoding.Unicode;

    public static string SerializeToString(object obj)
    {
        byte[] byteArray = BinarySerializeObject(obj);
        return Convert.ToBase64String(byteArray);
    }

    public static T DeSerializeFromString<T>(string input)
    {
        byte[] byteArray = Convert.FromBase64String(input);
        return BinaryDeserializeObject<T>(byteArray);
    }

    /// <summary>
    /// Takes a byte array and deserializes it back to its type of <see cref="T"/>
    /// </summary>
    /// <typeparam name="T">The Type to deserialize to</typeparam>
    /// <param name="serializedType">The object as a byte array</param>
    /// <returns>The deserialized type</returns>
    public static T BinaryDeserializeObject<T>(byte[] serializedType)
    {
        if (serializedType == null)
            throw new ArgumentNullException("serializedType");

        if (serializedType.Length.Equals(0))
            throw new ArgumentException("serializedType");

        T deserializedObject;

        using (MemoryStream memoryStream = new MemoryStream(serializedType))
        {
            BinaryFormatter deserializer = new BinaryFormatter();
            deserializedObject = (T)deserializer.Deserialize(memoryStream);
        }

        return deserializedObject;
    }

    /// <summary>
    /// Takes an object and serializes it into a byte array
    /// </summary>
    /// <param name="objectToSerialize">The object to serialize</param>
    /// <returns>The object as a <see cref="byte"/> array</returns>
    public static byte[] BinarySerializeObject(object objectToSerialize)
    {
        if (objectToSerialize == null)
            throw new ArgumentNullException("objectToSerialize");

        byte[] serializedObject;

        using (MemoryStream stream = new MemoryStream())
        {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, objectToSerialize);
            serializedObject = stream.ToArray();
        }

        return serializedObject;
    }

}

HTH