c# - ¿Cuál es el punto de la interfaz ISerializable?
(4)
Parece que puedo serializar clases que no tienen esa interfaz, por lo que no tengo claro su propósito.
Con el ISerializable
puede escribir métodos personalizados en su objeto para hacerse cargo de la serialización cuando realice una serialización binaria, para serializar sus objetos de una manera diferente a como lo hará el enfoque predeterminado utilizado por BinaryFormatter.
En otras palabras, si el enfoque predeterminado serializa su objeto de una manera diferente a la forma en que desea que se serialice, puede implementar ISerializable para un control completo. Tenga en cuenta que de la mano con ISerializable, también hay un constructor personalizado que debe implementar.
Por supuesto, XmlSerialization solo usará propiedades, ISerializable no tiene nada que ver con la serialización XML.
Gracias Marc y Pop por los comentarios, me apresuré un poco con mi primera respuesta.
Las clases se pueden serializar en .NET de una de estas dos maneras:
- Marque la clase con
SerializableAttribute
ySerializableAttribute
todos los campos que no desea que seNonSerialized
con el atributoNonSerialized
serializado. (Como señala Marc Gravell,BinaryFormatter
, que es la clase que se usa normalmente para formatear objetosISerializable
, serializa automáticamente todos los campos a menos que estén marcados específicamente de otra manera). - Implementación de la interfaz
ISerializable
para una serialización totalmente personalizada.
El primero es más fácil de usar, ya que simplemente implica marcar declaraciones con atributos, pero tiene un poder limitado. Este último permite más flexibilidad pero requiere un esfuerzo significativamente mayor para implementar. Cuál debes usar depende completamente del contexto.
Con respecto a este último ( ISerializable
) y su uso, he citado de la página de MSDN para la interfaz:
Cualquier clase que pueda ser serializada debe estar marcada con SerializableAttribute. Si una clase necesita controlar su proceso de serialización, puede implementar la interfaz ISerializable. El formateador llama a GetObjectData en el momento de la serialización y llena la información de SerializationInfo suministrada con todos los datos necesarios para representar el objeto. El formateador crea un SerializationInfo con el tipo del objeto en el gráfico. Los objetos que necesitan enviar proxies por sí mismos pueden usar los métodos FullTypeName y AssemblyName en SerializationInfo para cambiar la información transmitida.
En el caso de la herencia de clase, es posible serializar una clase que se deriva de una clase base que implementa ISerializable. En este caso, la clase derivada debe llamar a la implementación de la clase base de GetObjectData dentro de su implementación de GetObjectData. De lo contrario, los datos de la clase base no se serializarán.
Para hacer un objeto "transportable", tienes que serializarlo. Por ejemplo, si desea transferir datos de objetos utilizando .NET Remoting o Web Services, debe proporcionar métodos que serialicen sus datos de objetos, reduciendo sus instancias de objetos a un formato transportable que represente una representación de alta fidelidad del objeto.
Luego, también puede tomar la representación serializada, transportarla a otro contexto, como una máquina diferente, y reconstruir su objeto original.
Al implementar la interfaz ISerializable
, una clase debe proporcionar el método GetObjectData que se incluye en la interfaz, así como un constructor especializado que está especializado en aceptar dos parámetros: una instancia de SerializationInfo y una instancia de StreamingContext.
Si sus clases no requieren un control preciso de su estado de objeto, entonces podría usar el atributo [Serializable]
. Las clases que requieren más control sobre el proceso de serialización pueden implementar la interfaz ISerializable.
ISerializable
se utiliza para proporcionar una serialización binaria personalizada, generalmente para BinaryFormatter
(y tal vez con fines remotos). Sin él, utiliza los campos, que pueden ser:
- ineficiente; si hay campos que solo se usan para la eficiencia en el tiempo de ejecución, pero se pueden eliminar para la serialización (por ejemplo, un diccionario puede verse diferente cuando se serializa)
- ineficiente; ya que incluso para los campos que se necesitan, debe incluir muchos metadatos adicionales
- inválido; si hay campos que no se pueden serializar (como los delegados de eventos, aunque se pueden marcar
[NonSerialized]
) - frágil; su serialización ahora está vinculada a los nombres de campo , pero los campos deben ser un detalle de implementación; Véase también ofuscación, serialización y propiedades implementadas automáticamente.
Al implementar ISerializable
puede proporcionar su propio mecanismo de serialización binario. Tenga en cuenta que el equivalente xml de esto es IXmlSerializable
, tal como lo usa XmlSerializer
etc.
Para fines de DTO, se debe evitar BinaryFormatter
: cosas como xml (a través de XmlSerializer
o DataContractSerializer
) o json son buenas, al igual que los formatos multiplataforma como los búferes de protocolo.
Para completar, protobuf-net incluye ganchos para ISerializable
(lo que le permite usar un formato binario portátil sin escribir mucho código), pero BinaryFormatter
no sería su primera opción aquí de todos modos.