web-dev-qa-db-fra.com

Quel est l'intérêt de l'interface ISerializable?

Il semble que je puisse sérialiser des classes qui n'ont pas cette interface, donc je ne suis pas clair sur son objectif.

49
leora

ISerializable est utilisé pour fournir une sérialisation binaire personnalisée, généralement pour BinaryFormatter (et peut-être à des fins d'accès distant). Sans lui, il utilise les champs, qui peuvent être:

  • inefficace; s'il existe des champs qui ne sont utilisés que pour l'efficacité au moment de l'exécution, mais qui peuvent être supprimés pour la sérialisation (par exemple, un dictionnaire peut sembler différent lorsqu'il est sérialisé)
  • inefficace; car même pour les champs qui sont nécessaires, il doit inclure beaucoup de métadonnées supplémentaires
  • invalide; s'il y a des champs qui ne peuvent pas être sérialisés (comme les délégués d'événement, bien qu'ils puissent être marqués [NonSerialized])
  • fragile; votre sérialisation est maintenant liée au champ noms - mais les champs sont censés être un détail d'implémentation; voir aussi Obfuscation, sérialisation et propriétés implémentées automatiquement

En implémentant ISerializable, vous pouvez fournir votre propre mécanisme de sérialisation binaire. Notez que l'équivalent xml de ceci est IXmlSerializable, tel qu'utilisé par XmlSerializer etc.

Pour les besoins de DTO, BinaryFormatter devrait être évité - des choses comme xml (via XmlSerializer ou DataContractSerializer) ou json sont bonnes, tout comme les formats multiplateformes comme les tampons de protocole.

Pour être complet, protobuf-net inclut des hooks pour ISerializable (vous permettant d'utiliser un format binaire portable sans écrire beaucoup de code), mais BinaryFormatter ne serait pas votre premier choix ici de toute façon.

65
Marc Gravell

Les classes peuvent être sérialisées dans .NET de deux manières:

  1. Marquer la classe avec SerializableAttribute et décorer tous les champs dont vous ne voulez pas être sérialisés avec le NonSerialized attribut. (Comme le souligne Marc Gravell, BinaryFormatter, qui est la classe généralement utilisée pour formater les objets ISerializable, sérialise automatiquement tous les champs sauf s'ils sont spécifiquement marqués autrement.)
  2. Implémentation de l'interface ISerializable pour une sérialisation entièrement personnalisée.

Le premier est plus simple à utiliser car il implique simplement de marquer des déclarations avec des attributs, mais sa puissance est limitée. Ce dernier permet plus de flexibilité mais demande beaucoup plus d'efforts à mettre en œuvre. Lequel vous devez utiliser dépend entièrement du contexte.

Concernant ce dernier (ISerializable) et son utilisation, j'ai cité la page MSDN pour l'interface:

Toute classe qui pourrait être sérialisée doit être marquée avec le SerializableAttribute. Si une classe doit contrôler son processus de sérialisation, elle peut implémenter l'interface ISerializable. Le formateur appelle GetObjectData au moment de la sérialisation et remplit le SerializationInfo fourni avec toutes les données nécessaires pour représenter l'objet. Le formateur crée un SerializationInfo avec le type de l'objet dans le graphique. Les objets qui doivent envoyer des proxys pour eux-mêmes peuvent utiliser les méthodes FullTypeName et AssemblyName sur SerializationInfo pour modifier les informations transmises.

Dans le cas de l'héritage de classe, il est possible de sérialiser une classe qui dérive d'une classe de base qui implémente ISerializable. Dans ce cas, la classe dérivée doit appeler l'implémentation de classe de base de GetObjectData dans son implémentation de GetObjectData. Sinon, les données de la classe de base ne seront pas sérialisées.

9
Noldorin

Avec le ISerializable, vous pouvez écrire des méthodes personnalisées dans votre objet pour prendre en charge la sérialisation lors de la sérialisation binaire, pour sérialiser vos objets d'une manière différente de ce que l'approche par défaut utilisée par BinaryFormatter fera.

En d'autres termes, si l'approche par défaut sérialise votre objet d'une manière différente de la façon dont vous souhaitez qu'il sérialise, vous pouvez implémenter ISerializable pour un contrôle complet. Notez que main dans la main avec ISerializable, il existe également un constructeur personnalisé que vous devez implémenter.

XmlSerialization n'utilisera bien sûr que des propriétés, ISerializable n'a rien à voir avec la sérialisation XML.

Merci Marc et Pop pour les commentaires, j'étais un peu précipité avec ma première réponse.

Pour rendre un objet "transportable", vous devez le sérialiser. Par exemple, si vous souhaitez transférer des données d'objet à l'aide de .NET Remoting ou de services Web, vous devez fournir des méthodes qui sérialisent vos données d'objet, réduisant vos instances d'objet dans un format transportable qui représente une représentation haute fidélité de l'objet.

Vous pouvez ensuite également prendre la représentation sérialisée, la transporter dans un autre contexte tel qu'une autre machine et reconstruire votre objet d'origine.

Lors de l'implémentation de l'interface ISerializable, une classe doit fournir la méthode GetObjectData incluse dans l'interface, ainsi qu'un constructeur spécialisé spécialisé pour accepter deux paramètres: une instance de SerializationInfo et une instance de StreamingContext.

Si vos classes ne nécessitent pas un contrôle fin de leur état d'objet, vous pouvez simplement utiliser [Serializable] attribut. Les classes qui nécessitent plus de contrôle sur le processus de sérialisation peuvent implémenter l'interface ISerializable.

3
splattne