Net, конфігурація об'єктів сериализации

Щоб зробити об'єкт доступним для служб сериализации .NET, знадобиться тільки декорувати кожен пов'язаний клас (або структуру) атрибутом [Serializable]. Якщо з'ясовується, що певний тип має члени-дані, які не повинні (або не можуть) брати участь в схемі сериализации, можна помітити такі поля атрибутом [NonSerialized]. Це допомагає скоротити розмір збережених даних, за умови, що в Серіалізуемое класі є змінні-члени, які не слід "запам'ятовувати" (наприклад, фіксовані значення, випадкові значення, короткочасні дані і т.п.).

Для початку створимо нове консольний додаток. Додамо в нього новий клас по імені Radio, позначений атрибутом [Serializable], у якого виключається одна змінна-член (radioID), позначена атрибутом [NonSerialized] і тому не зберігається в специфіковані потоці даних:

Потім додамо два додаткових типу, що представляють базові класи JamesBondCar і Car (обидва вони також позначені атрибутом [Serializable]), і визначимо в них такі поля даних:

Майте на увазі, що атрибут [Serializable] не може успадковуватися від батьківського класу. Тому при спадкуванні типу, позначеного [Serializable], дочірній клас також повинен бути позначений [Serializable] або ж його не можна буде зберегти в потоці. Фактично всі об'єкти в графі об'єктів повинні бути позначені атрибутом [Serializable]. Спроба серіалізовать несеріалізуемий об'єкт з використанням BinaryFormatter або SoapFormatter призводить до виключення SerializationException під час виконання.

Зверніть увагу, що в кожному з цих класів поля даних визначені як public, це зроблено для спрощення прикладу. Звичайно, приватні дані, представлені загальнодоступними властивостями, були б більш кращі з точки зору ООП. Також для простоти в цих типах не визначились ніякі спеціальні конструктори, і тому все неініціалізовані поля даних отримають очікувані значення за замовчуванням.

Залишивши в стороні принципи ООП, можна запитати: якого визначення полів даних типу вимагають різні форматер, щоб серіалізовать їх в потік? Відповідь така: в залежності від обставин. Якщо ви зберігаєте стан об'єкта, використовуючи BinaryFormatter або SoapFormatter. то різниці ніякої. Ці типи запрограмовані для сериализации усіх серіалізуемость полів типу, незалежно від того, представлені вони загальнодоступними полями, приватними полями або приватними полями з відповідними загальнодоступними властивостями.

Однак згадайте, що якщо є елементи даних, які не повинні зберігатися в графі об'єктів, можна вибірково помітити загальнодоступні або приватні поля атрибутом [NonSerialized], як зроблено із строковими полями в типі Radio.

Однак ситуація істотно змінюється, якщо ви збираєтеся застосовувати тип XmlSerializer. Цей тип буде серіалізовать тільки Серіалізуемое загальнодоступні поля даних або приватні поля, представлені загальнодоступними властивостями. Приватні дані, які не представлені властивостями, просто ігноруються. Наприклад, розглянемо наступний Серіалізуемое тип Person:

При обробці BinaryFormatter або SoapFormatter виявиться, що поля isAlive, personAge і fName зберігаються в обраному потоці. Однак XmlSerializer не збереглося значення personAge, оскільки ця частина приватних даних не Інкапсульована в властивість. Щоб зберігати вік персони за допомогою XmlSerializer, це поле знадобиться визначити як public або ж инкапсулировать його в загальнодоступному властивості.

Схожі статті