Qual è il punto dell'interfaccia ISerializable?
-
03-07-2019 - |
Domanda
Mi sembra di poter serializzare le classi che non hanno quell'interfaccia, quindi non sono chiaro sul suo scopo.
Soluzione
ISerializable
viene utilizzato per fornire una serializzazione binaria personalizzata, in genere per BinaryFormatter
(e forse per scopi remoti). Senza di essa, utilizza i campi, che possono essere:
- inefficiente; se ci sono campi che vengono utilizzati solo per l'efficienza in fase di esecuzione, ma possono essere rimossi per la serializzazione (ad esempio, un dizionario può apparire diverso quando serializzato)
- inefficiente; come anche per i campi necessari, deve includere molti metadati aggiuntivi
- non valida; se ci sono campi che non possono essere serializzati (come i delegati di eventi, sebbene possano essere contrassegnati
[Non serializzati]
) - fragile; la serializzazione è ora associata ai nomi field - ma i campi devono essere un dettaglio di implementazione; vedi anche Offuscamento, serializzazione e proprietà implementate automaticamente
Implementando ISerializable
puoi fornire il tuo meccanismo di serializzazione binaria. Si noti che l'equivalente xml di questo è IXmlSerializable
, utilizzato da XmlSerializer
ecc.
Ai fini DTO, BinaryFormatter
dovrebbe essere evitato - cose come xml (tramite XmlSerializer
o DataContractSerializer
) o json sono buone, così come sono incrociate formati di piattaforma come i buffer di protocollo.
Per completezza, protobuf-net include hook per ISerializable
(che consente di utilizzare un formato binario portatile senza scrivere un sacco di codice), ma BinaryFormatter
non sarebbe la tua prima scelta qui comunque.
Altri suggerimenti
Le classi possono essere serializzate in .NET in due modi:
- Contrassegnare la classe con
SerializableAttribute
e decorare tutti i campi che non si desidera serializzare con l'attributoNon serializzato
. (Come sottolinea Marc Gravell,BinaryFormatter
, che è la classe generalmente utilizzata per formattare gli oggettiISerializable
, serializza automaticamente tutti i campi a meno che non siano specificamente contrassegnati diversamente.) - Implementazione dell'interfaccia
ISerializable
per la serializzazione completamente personalizzata.
Il primo è più semplice da usare in quanto comporta semplicemente la marcatura di dichiarazioni con attributi, ma è limitato nella sua potenza. Quest'ultimo consente una maggiore flessibilità ma richiede uno sforzo significativamente maggiore per l'implementazione. Quale dovresti usare dipende completamente dal contesto.
Riguardo a quest'ultimo ( ISerializable
) e al suo utilizzo, ho citato da pagina MSDN per l'interfaccia:
Qualsiasi classe che potrebbe essere serializzata deve essere contrassegnato con il simbolo SerializableAttribute. Se una lezione deve controllare la sua serializzazione processo, può implementare il Interfaccia ISerializable. The Formatter chiama GetObjectData a tempo di serializzazione e popola il fornito SerializationInfo con tutto i dati richiesti per rappresentare il oggetto. Il formatter crea un SerializationInfo con il tipo di oggetto nel grafico. Oggetti che necessitano per inviare proxy per se stessi possono utilizzare FullTypeName e AssemblyName metodi su SerializationInfo da modificare le informazioni trasmesse.
In caso di eredità di classe, esso è possibile serializzare una classe che deriva da una classe base che implementa ISerializable. In questo caso, la classe derivata dovrebbe chiamare l'implementazione della classe base di GetObjectData al suo interno implementazione di GetObjectData. Altrimenti, i dati dalla base la classe non verrà serializzata.
Con ISerializable
puoi scrivere metodi personalizzati nel tuo oggetto per assumere la serializzazione durante la serializzazione binaria, per serializzare i tuoi oggetti in un modo diverso da quello che farà l'approccio predefinito usato da BinaryFormatter.
In altre parole, se l'approccio predefinito serializza l'oggetto in modo diverso rispetto a come si desidera serializzare, è possibile implementare ISerializable per un controllo completo. Nota che, insieme a ISerializable, c'è anche un costruttore personalizzato che dovresti implementare.
XmlSerialization utilizzerà ovviamente solo proprietà, ISerializable non ha nulla a che fare con la serializzazione XML.
Grazie a Marc e Pop per i commenti, ero un po 'frettoloso con la mia prima risposta.
Per rendere un oggetto "trasportabile", è necessario serializzarlo. Ad esempio, se si desidera trasferire i dati degli oggetti utilizzando .NET Remoting o i servizi Web, è necessario fornire metodi che serializzano i dati degli oggetti, riducendo le istanze degli oggetti in un formato trasportabile che rappresenta una rappresentazione ad alta fedeltà dell'oggetto.
Quindi puoi anche prendere la rappresentazione serializzata, trasportarla in un altro contesto come una macchina diversa e ricostruire il tuo oggetto originale.
Quando si implementa l'interfaccia ISerializable
, una classe deve fornire il metodo GetObjectData incluso nell'interfaccia, nonché un costruttore specializzato specializzato ad accettare due parametri: un'istanza di SerializationInfo e un'istanza di StreamingContext.
Se le tue classi non richiedono un controllo approfondito del loro stato dell'oggetto, puoi semplicemente usare l'attributo [Serializable]
. Le classi che richiedono un maggiore controllo sul processo di serializzazione possono implementare l'interfaccia ISerializable.