Сериализация и десериализация графа объектов с помощью BinaryFormatter

Я пытаюсь сериализовать свой граф объектов в строку, а затем десериализовать его из строки. Объект сериализуется просто отлично, если я это сделаю

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;
     }
}

Приведенный выше код работает, но сериализуется в строку и пытается десериализовать ту же строку, как это

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());
     }
}

Выдает исключение

Нет идентификатора сборки для типа объекта "1936026741 Core.Sebring.BusinessObjects.Search.Search".

Любая помощь приветствуется. Спасибо.


person andrewramka    schedule 16.02.2013    source источник


Ответы (1)


Вот некоторый код, который будет делать то, что вы хотите (я думаю) - но я должен спросить - почему вы хотите сериализовать в такую ​​​​строку?

Если класс достаточно прост для сериализации в строку, используйте XML-сериализатор, с которым гораздо проще работать; если вы хотите сериализовать его на диск, двоично записать его в файл, а если он сложный, и вы сериализуете его для передачи, рассмотрите возможность использования чего-то вроде protobuf-net.

Я думаю, что суть вашей проблемы в том, что вы пытаетесь использовать кодировку ASCII - я использую кодировку Base64.

В любом случае - вот (я только что догадался о вашем классе поиска!)

 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;
    }

}

ХТН

person Jay    schedule 16.02.2013
comment
+1 для кодировки Base64 (для представления двоичных данных в формате строки ASCII). - person Sergey Vyacheslavovich Brunov; 17.02.2013
comment
Я сериализую в строку, чтобы сохранить ее в базе данных. Если есть лучший метод, я открыт для предложений. - person andrewramka; 17.02.2013
comment
Можете ли вы обновить исходный вопрос, включив в него класс поиска? Трудно советовать, когда я не знаю, что вы пытаетесь сериализовать. - person Jay; 17.02.2013