Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Сериализация List<T> со вложенными листами, которые содержат одни и те же объекты 
:(
    Опции темы
Felan
Дата 28.8.2009, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 284
Регистрация: 2.8.2007
Где: Самара

Репутация: нет
Всего: 7



Че-то поиск не помог... 
Есть такой класс:

Код

    public class Men
    {
        public static readonly DateTime MaxBithdayDate = new DateTime(9998, 12, 31);
        public static readonly DateTime MinBithdayDate = new DateTime(1753, 1, 1);

        public string Name { get; set; }
        public string SecondName { get; set; }
        public string Family { get; set; }

        private DateTime _Birthday = MinBithdayDate;
        public DateTime Birthday
        {
            get { return _Birthday; }
            set
            {
                if ((value < MinBithdayDate) || (value > MaxBithdayDate))
                {
                    throw new ArgumentOutOfRangeException();
                }
                _Birthday = value;
            }
        }

        private Address _Address = new Address();
        public Address Address
        {
            get { return _Address; }
            set
            {
                if(value == null)
                {
                    throw new ArgumentNullException();
                }
                _Address = value;
            }
        }

        public string FullName
        {
            get 
            { 
                return String.Format("{0} {1} {2}", Family, Name, SecondName); 
            }
        }

        private List<Men> _Relatives = new List<Men>();
        public List<Men> Relatives
        {
            get
            {
                return _Relatives;
            }
        }


        public Men( string name, string secondName, string family, DateTime birthday, string city, string street, uint houseNumber, uint flatNumber )
        {
            Name = name;
            SecondName = secondName;
            Family = family;
            Birthday = birthday;
            Address.City = city;
            Address.Street = street;
            Address.HouseNumber = houseNumber;
            Address.FlatNumber = flatNumber;
        }

        public Men(): this ("", "", "", MinBithdayDate, "", "", 0, 0)
        {
        }

        public void SaveData( string filename )
        {
            var sr = new XmlSerializer( _Relatives.GetType() );
            using( var filestream = new FileStream( filename, FileMode.Create ) )
            {
                sr.Serialize( filestream, _Relatives );
            }
        }

        public void LoadData(string filename)
        {
            if (!File.Exists(filename))
            {
                return;
            }
            var sr = new XmlSerializer( _Relatives.GetType() );
            using( var filestream = new FileStream( filename, FileMode.Open ) )
            {
                _Relatives = (List<Men>) sr.Deserialize(filestream);
            }
        }
    }
}



Ну еще он содержит класс Address:


 
Код

   public class Address
    {
        public Address(string city, string street, uint houseNumber, uint flatNumber)
        {
            City = city;
            Street = street;
            HouseNumber = houseNumber;
            FlatNumber = flatNumber;
        }

        public Address(): this("", "", 0, 0)
        {
        }

        public string City { get; set; }
        public string Street { get; set; }
        public uint HouseNumber { get; set; }
        public uint FlatNumber { get; set; }

        public override string ToString()
        {
            return String.Format( "г. {0}, ул. {1}, д. {2}, кв. {3}.", City, Street, HouseNumber, FlatNumber );
        }
    }



Соотествественно в программе создаются классы Men и в их коллекции Relatives добавляются другие классы Men.

Если один экземпляр Men добавить в Relatives разных других экзепляров Men, например так:


Код

var men1 = new Men(...);

var men2 = new Men (...);

var men3 = new Men (...);

var men4 = new Men(...);

men1.Relatives.Add(men2);

men1.Relatives.Add(men3);

men2.Relatives.Add(men4);

men3.Relatives.Add(men4);




То при вызове метода men1.SaveData объект men4 будет записан два раза. При десериализации, соответственно мы получим что у объектов men2 и men3 будут разные объекты men4 и men4'.

Как правильно сделать сериализацию, что бы объект men4 не дублировался? 


--------------------
// Любая сложная система - это темный лес. Каждый в этом лесу протаптывает свои тропинки, по ним и бегает. Лишь изредка, сходя с них, мы находим много интересного, а порою и страшного.
PM MAIL WWW ICQ   Вверх
mihryak
Дата 29.8.2009, 00:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 731
Регистрация: 28.4.2007
Где: С-Пб

Репутация: 19
Всего: 36



Цитата(Felan @  28.8.2009,  23:33 Найти цитируемый пост)
Как правильно сделать сериализацию, что бы объект men4 не дублировался? 

то, что он дублируется - ещё полбеды, добавь в четвёртому человеку ([зануда mode on]men - множественное число, правильнее будет man[зануда mode off]) в коллекцию первого, и всё вообще перестанет сериализоваться, т.к. xml-сериализация не поддерживает циклических ссылок. в отличие от бинарной -  BinaryFormatter
Код

        public void SaveData(string filename)
        {
            using (var filestream = new FileStream(filename, FileMode.Create))
            {
                var formatter = new BinaryFormatter();
                formatter.Serialize(filestream, _Relatives);
            }
        }
        public void LoadData(string filename)
        {
            if (!File.Exists(filename))
            {
                return;
            }

            using (var filestream = new FileStream(filename, FileMode.Open))
            {
                var formatter = new BinaryFormatter();
                _Relatives = (List<Men>)formatter.Deserialize(filestream);
            }
        }

нужно будет ещё пометить классы Men и Address атрибутом [Serializable]
в результате все объекты будут в единственном числе
Код

            var men1 = new Men { Name = "men1" };
            var men2 = new Men { Name = "men2" };
            var men3 = new Men { Name = "men3" };
            var men4 = new Men { Name = "men4" };
            men1.Relatives.Add(men2);
            men1.Relatives.Add(men3);
            men2.Relatives.Add(men4);
            men3.Relatives.Add(men4);

            men4.Relatives.Add(men1);

            men1.SaveData("test.xml");
            men1.LoadData("test.xml");

            Debug.Assert(ReferenceEquals(men1.Relatives[0].Relatives[0], men1.Relatives[1].Relatives[0]));
            Debug.Assert(men1.Relatives[1].Relatives[0].Relatives.Count == 1);
            men1.Relatives[0].Relatives[0].Relatives.Clear();
            Debug.Assert(men1.Relatives[1].Relatives[0].Relatives.Count == 0);

если ссылки односторонние, т.е. наличие ссылки, например, первого человека на второго не подразумевает наличия ссылки второго на первого, то работать будет

в то же время, мне почему-то кажется такая система управления ссылками довольно шаткой, впрочем, я не знаю задачу, быть может, всё в порядке
PM MAIL ICQ   Вверх
Felan
Дата 29.8.2009, 11:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 284
Регистрация: 2.8.2007
Где: Самара

Репутация: нет
Всего: 7



Цитата(mihryak @  29.8.2009,  02:43 Найти цитируемый пост)
[зануда mode on]men - множественное число, правильнее будет man[зануда mode off]

smile Точно, че-то прогнал smile


Цитата(mihryak @  29.8.2009,  02:43 Найти цитируемый пост)
т.к. xml-сериализация не поддерживает циклических ссылок. в отличие от бинарной -  BinaryFormatter

Прочитал уже про это... Плохо...

Ну в принципе такое возможно. Но бинарная же вроде поддерживает циклические ссылки?


Цитата(mihryak @  29.8.2009,  02:43 Найти цитируемый пост)
в то же время, мне почему-то кажется такая система управления ссылками довольно шаткой, впрочем, я не знаю задачу, быть может, всё в порядке 

А можно узнать твой вариант?


--------------------
// Любая сложная система - это темный лес. Каждый в этом лесу протаптывает свои тропинки, по ним и бегает. Лишь изредка, сходя с них, мы находим много интересного, а порою и страшного.
PM MAIL WWW ICQ   Вверх
mihryak
Дата 29.8.2009, 11:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 731
Регистрация: 28.4.2007
Где: С-Пб

Репутация: 19
Всего: 36



Цитата(Felan @  29.8.2009,  12:09 Найти цитируемый пост)
бинарная же вроде поддерживает циклические ссылки?

угу, вполне. после десериализации объекты будут в единственном числе. тестовый код это демонстрирует
Цитата(Felan @  29.8.2009,  12:09 Найти цитируемый пост)
можно узнать твой вариант? 

мне в голову приходит единый манагер ссылок, задаваемый человеку при его создании, через который люди получают и обновляют своих relatives
т.е. люди отдельно, ссылки отдельно, что-то вроде
Код

class Men
{
    public void AddRelative(Men men)
    {
        manager.AddRelative(this, men);
    }
}

в таком случае появится возможность менять механизмы работы с ссылками, не меняя кода, их использующего (например, однонаправленные заменить на двунаправленные), пропадёт вероятность рассинхронизации коллекций ссылок у людей и т.п.

но, опять-таки, если в данный момент единственная проблема - сериализация коллекций, то и менять ничего смысла нет, к чему неоправданное усложнение системы?..
PM MAIL ICQ   Вверх
Felan
Дата 29.8.2009, 23:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 284
Регистрация: 2.8.2007
Где: Самара

Репутация: нет
Всего: 7



Да. Это слишком уже будет для моей задачи...
Спасибо.


--------------------
// Любая сложная система - это темный лес. Каждый в этом лесу протаптывает свои тропинки, по ним и бегает. Лишь изредка, сходя с них, мы находим много интересного, а порою и страшного.
PM MAIL WWW ICQ   Вверх
neutrino
Дата 31.8.2009, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Gothic soul
****


Профиль
Группа: Модератор
Сообщений: 3041
Регистрация: 25.3.2002
Где: Верхняя Галилея, Кармиэль

Репутация: 3
Всего: 62



Стоп!
Можно написать свой собственный сериализатор/десериализатор. Мы так и сделали. Поддерживается все и циклы и указатели на один и тот же объект.

Добавлено через 1 минуту и 33 секунды
Все кстати довольно просто: запоминаем в HashSet<> сериализованные объекты, чтобы не сериализовывать их еще раз...

Добавлено через 7 минут и 7 секунд
Гы, кстати 2: И без обязательных public конструкторов smile


--------------------
The truth comes from within ...

Покойся с миром, Vit 
PM MAIL WWW ICQ Skype GTalk   Вверх
mihryak
Дата 31.8.2009, 20:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 731
Регистрация: 28.4.2007
Где: С-Пб

Репутация: 19
Всего: 36



Цитата(neutrino @  31.8.2009,  15:50 Найти цитируемый пост)
без обязательных public конструкторов

они и при бинарной сериализации не особо нужны
Цитата(neutrino @  31.8.2009,  15:50 Найти цитируемый пост)
Можно написать свой собственный сериализатор/десериализатор. Мы так и сделали. Поддерживается все и циклы и указатели на один и тот же объект.

а можно хотя бы в общих чертах описать механизм его работы?
Цитата(neutrino @  31.8.2009,  15:50 Найти цитируемый пост)
запоминаем в HashSet<> сериализованные объекты, чтобы не сериализовывать их еще раз...

HashSet<?> какого именно типа? object и через Equals/GetHashCode сравнение?
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0704 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.