Кажется, я могу сериализовать классы, у которых нет этого интерфейса, поэтому я не понимаю его назначение.
В чем смысл интерфейса ISerializable?
Ответ 1
ISerializable используется для предоставления пользовательской двоичной сериализации, обычно для BinaryFormatter (и, возможно, для целей удаленного использования). Без него он использует поля, которые могут быть:
- неэффективна; если есть поля, которые используются только для эффективности во время выполнения, но могут быть удалены для сериализации (например, словарь может выглядеть по-разному при сериализации)
- неэффективна; так как даже для необходимых полей необходимо включить много дополнительных метаданных
- недействительным; если есть поля, которые не могут быть сериализованы (например, делегаты событий, хотя они могут быть отмечены
[NonSerialized]) - ломкими; ваша сериализация теперь привязана к именам полей, но поля предназначены для детализации реализации; см. также Обфускация, сериализация и автоматически реализованные свойства
Внедряя ISerializable, вы можете предоставить свой собственный механизм двоичной сериализации. Обратите внимание, что эквивалент xml это IXmlSerializable, используемый XmlSerializer и т.д.
Для целей DTO следует избегать BinaryFormatter - такие вещи, как xml (через XmlSerializer или DataContractSerializer) или json, хороши, как и кросс-платформенные форматы, такие как буферы протоколов.
Для полноты, protobuf-net включает в себя крючки для ISerializable (позволяя вам использовать переносимый двоичный формат без написания большого количества кода), но BinaryFormatter не будет вашим первым выбором здесь в любом случае.
Ответ 2
Классы могут быть сериализованы в .NET одним из двух способов:
- Маркировка класса с помощью
SerializableAttributeи декорирование всех полей, которые вы не хотите сериализовать с помощью атрибутаNonSerialized. (Как отмечает Марк Гравелл,BinaryFormatter, который является классом, обычно используемым для форматирования объектовISerializable, автоматически сериализует все поля, если они специально не отмечены иначе.) - Внедрение интерфейса
ISerializableдля полной пользовательской сериализации.
Первое проще использовать, поскольку оно просто включает в себя маркировку объявлений с атрибутами, но ограничено по мощности. Последнее обеспечивает большую гибкость, но требует значительно больших усилий для реализации. Какой из них вы должны использовать, полностью зависит от контекста.
Что касается последнего (ISerializable) и его использования, я процитировал со страницы
Ответ 3
С помощью ISerializable вы можете писать собственные методы в своем объекте, чтобы взять сериализацию при выполнении двоичной сериализации, чтобы сериализовать ваши объекты по-другому, чем то, что сделает подход по умолчанию, используемый BinaryFormatter.
Другими словами, если подход по умолчанию сериализует ваш объект по-другому, чем то, как вы хотите его сериализовать как, вы можете реализовать ISerializable для полного контроля. Обратите внимание, что рука об руку с ISerializable, там также должен быть реализован пользовательский конструктор.
XmlSerialization, конечно, будет использовать только свойства, ISerializable не имеет ничего общего с сериализацией XML.
Спасибо Marc и Pop за комментарии, я немного поспешил с моим первым ответом.
Ответ 4
Чтобы сделать объект "переносимым", вы должны его сериализовать. Например, если вы хотите передать данные объекта с помощью .NET Remoting или Web Services, вам необходимо предоставить методы, которые сериализуют ваши данные объекта, уменьшая количество экземпляров объекта в переносимом формате, который представляет собой верное представление объекта.
Затем вы также можете взять сериализованное представление, перенести его в другой контекст, например, на другой компьютер, и перестроить исходный объект.
При реализации интерфейса ISerializable класс должен предоставить метод GetObjectData, который включен в интерфейс, а также специализированный конструктор, специализированный для принятия двух параметров: экземпляр SerializationInfo и экземпляр StreamingContext.
Если ваши классы не требуют мелкомасштабного управления своим состоянием объектов, вы можете просто использовать атрибут [Serializable]. Классы, требующие большего контроля над процессом сериализации, могут реализовать интерфейс ISerializable.