|
Rimettiamoci a studiare dopo un po’ di vacanza e un po’ di eccessivo lavoro (tanto per bilanciare).
Serialize or deserialize an object or an object graph using runtime serialization techniques (System.Runtime.Serialization namespace) |
Le interfacce di serializzazione permettono di controllare tutto il processo e per implementarle è necessario implementare l’interfaccia ISerializable, che espone il metodo GetObjectData in cui viene effettuato il lavoro.
Ci provo:
[Serializable] //senza questo non va nulla
public class mioOggetto : ISerializable, IEquatable<mioOggetto >
{ private string nome;
private string cognome;
public mioOggetto(string n, string c)
{
nome = n;
cognome = c;
}
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("AttributoNome", nome);
info.AddValue("AttributoCognome", cognome);
}
#region IEquatable<mioOggetto> Members
public bool Equals(mioOggetto obj2)
{
if (obj2.nome == nome && obj2.cognome == cognome ) return true;
else return false;
}
#endregion
}
Per la serializzazione ho bisogno di un oggetto che implementa l’interfaccia IFormatter, per esempio System.Runtime.Serialization.Formatters.Soap.SoapFormatter , e anche di uno stream cosi’ me lo salvo su disco e controllo il risultato.
static void Main(string[] args)
{
mioOggetto obj1 = new mioOggetto("Donald","Duck");
mioOggetto obj2 = new mioOggetto("Mickey","Mouse");
IFormatter fmt = new System.Runtime.Serialization.Formatters.Soap.SoapFormatter();
System.IO.Stream stream = new System.IO.FileStream("c:\\temp\\testSerialize.xml", System.IO.FileMode.OpenOrCreate );
fmt.Serialize( stream, obj1);
fmt.Serialize( stream, obj2);
stream.Close();
}
Il risultato è un file file xml..cosi’:
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" …….. /">
<SOAP-ENV:Body>
<a1:mioOggetto id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/Test3/Test3%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
<AttributoNome id="ref-3">Donald</AttributoNome>
<AttributoCognome id="ref-4">Duck</AttributoCognome>
</a1:mioOggetto>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
<SOAP-ENV:……..
Per deserializzare il gioco è praticamente identico.. ho bisogno di un altro SoapFormatter e gli dico di deserializzare, aggiungo al mio main le seguenti righe...
IFormatter fmt2 = new System.Runtime.Serialization.Formatters.Soap.SoapFormatter();
System.IO.Stream stream2 = new System.IO.FileStream("c:\\temp\\testSerialize.xml", System.IO.FileMode.Open );
mioOggetto ret1 = (mioOggetto) fmt2.Deserialize(stream2);
mioOggetto ret2 = (mioOggetto) fmt2.Deserialize(stream2);
if (ret1.Equals( obj1) ) Console.Write("Bene.");
if (ret2.Equals( obj2) ) Console.Write("..bene!");
Ma attenzione, il gioco non è finito, se si prova il tutto cosi’ la funzione Deserialize si imbufalisce perchè dice che non ha il costruttore adeguato per la classe. La soluzione? Ovvia, quando la si è scoperta: aggiungere il costruttore che prende gli stessi parametri della GetObjectData e fa il lavoro inverso. Cosi’:
public mioOggetto( SerializationInfo info, StreamingContext cnt)
{
nome = info.GetString ("AttributoNome") ;
cognome = info.GetString ("AttributoCognome");
}
Ci sono altre interfacce per controllare la serializzazione:
IDeserializationCallback: indica la classe deve essere richiamata quando la deserializzazione dell’intero insieme degli oggetti è completata.
IFormatterConverter: fornisce la connessione fra SerializationInfo e la classe formatter, in genere utilizzata per fare il parsing dei dati all’interno delle Info.
IObjectReference: indica che la classe è il riferimento ad un altro oggetto
ISerializationSurrogate: utilizzata per permettere ad un oggetto di effettuare la serializzazione di altri, magari logicamente dipendenti.