Проблемы с SerializationSurrogate при циклических ссылках
От: Silver_s Ниоткуда  
Дата: 29.06.09 11:51
Оценка:
Нужна двоичная сериализация без требований установки [Serializable]
Видно 3 варианта:
1) Самодельная реализация.
2) Через Reflector вытащить исходники BinaryFormatter,и связанных с ним классов , удалить код проверки [Serializable], компильнуть и юзать.
3) Заставить работать через SerializationSurrogate. Но что-то не выходит никак, с циклическими ссылками.

В чем может быть проблема, в приведенном коде?
Во время десериализации выскакивает exeption, якобы ID=3 прописано а такого объекта нет.
Кроме того GetObjectData, вызывается второй раз для того же объекта, на циклической ссылке (хотя и не зацикливается бесконечно).
Если не писать объект второй раз, а просто return, то все равно exception.

Странно что если Surrogate подключен при сериализации, а десериализация без сурогата, то нормально десериализуется.
А если сериализация без сурогата, десериализация с сурогатом дает тот же exception.

Значит проблема с десериализацией. Exception вылетает из ObjecManager во время разборок с сылками (Fixup...), еще до того как вызывается SetObjectData из сурогата.


    class CommonSerializationSurrogate : ISerializationSurrogate
    {
        // Method called to serialize object
        public void GetObjectData(Object obj,SerializationInfo info, StreamingContext context)
        {
            BindingFlags bf = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
            foreach (FieldInfo fi in obj.GetType().GetFields(bf))
                info.AddValue(fi.Name, fi.GetValue(obj));
        }
        // Method called to deserialize object
        public Object SetObjectData(Object obj,SerializationInfo info, StreamingContext context,ISurrogateSelector selector)
        {
            BindingFlags bf = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
            foreach (FieldInfo fi in obj.GetType().GetFields(bf))
                fi.SetValue(obj, info.GetValue(fi.Name, fi.FieldType));
            return obj;
        }
    }
    class CommonSurrogateSelector : ISurrogateSelector
    {
        public CommonSerializationSurrogate _Surrogate = new CommonSerializationSurrogate();
        public void ChainSelector(ISurrogateSelector selector){}
        public ISurrogateSelector GetNextSelector(){return null;}
        public ISerializationSurrogate GetSurrogate(Type type, StreamingContext context, out ISurrogateSelector selector)
        {
            selector = this;
            return _Surrogate;
        }     
    }

    [Serializable]
    class Cl1
    {
        public Cl2 cl2;
    }
    [Serializable]
    class Cl2
    {
        public Cl1 cl1;
    }


И использование:

            var cl2 = new Cl2();
            cl2.cl1 = new Cl1();
            cl2.cl1.cl2 = cl2;

            MemoryStream ms = new MemoryStream();
            BinaryFormatter bf = new BinaryFormatter();
            CommonSurrogateSelector ss = new CommonSurrogateSelector();
            bf.SurrogateSelector = ss;

            bf.Serialize(ms, cl2);
            ms.Position = 0;
            object obj = bf.Deserialize(ms);
Re: Проблемы с SerializationSurrogate при циклических ссылка
От: Kore Sar  
Дата: 29.06.09 12:43
Оценка:
S_>Нужна двоичная сериализация без требований установки [Serializable]
S_>Видно 3 варианта:
S_>1) Самодельная реализация.

Я бы вот так и поступил.
Извините, что не по теме.
Re[2]: Проблемы с SerializationSurrogate при циклических ссы
От: Silver_s Ниоткуда  
Дата: 29.06.09 14:37
Оценка:
Здравствуйте, Kore Sar, Вы писали:
S_>>1) Самодельная реализация.
KS>Я бы вот так и поступил.

Я тоже склоняюсь к этому варианту. Тем более что уже есть самодельная сериализация за день написаная, но без наворотов в виде обработки ISerialazable, [OnDeserialized],итд. Там где она используется навороты не нужны, в других местах стандартная.
Но хотелось объединить... видимо не получится.

А вот то, что объект сериализованый по-нормальному, удается десериализовать через сурогат только если не попадаются циклические ссылки.
Это уже похоже на серьезный баг. Причем падает еще до того как в сурогат управление попадает. Достаточно одного факта подключения сурогата.
Никто наверное эти сурогаты не использует. Был у них и раньше на сурогатах баг — через сурогаты нельзя было Value типы десериализовать, его поправили.

Пытался разобраться через Reflector, но там все так запутано, что за пару часов ничего там так и не понял.
Даже для самодельной сериализации, никакого полезного кода оттуда не скопируешь.

То ли кривыми руками писали BinaryFormater, то ли из-за наворотов (безопасность,маршилизация всякая,итд) так все сложно и запутанно получилось.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.