Serializzarre dei tipi Generics... cronologia di metà gennaio...

di Andrea Zani, in .NET2,

In questo periodo stavo giocando con la classe Profile del Framework 2. Questa classe è una delle grandi novità del nuovo asp.net 2.0, e permette la memorizzazione dei dati per ogni singolo utente (maggiori info qui). Dopo il primo entusiastico approccio ho cercato qualcosa di più complesso come l'uso di un tipo generics per le memorizzazione di alcuni dati per l'utente. I miei tentativi portano solo una marea di errori, e anche gente che ne sa più di me mi ha confermato che per ora non è possibile ottenere quello che mi ero prefissato almeno per ora (qui la breve discussione in merito, grazie Daniele).

Ok, cerco di risolvere con la creazione di una classe ereditandola da una generics come il Dictionary:

[Serializable]
public class MiaClasse : Dictionary<int, int>
{
 public MiaClasse() : base()
 { }
}

Dichiarando questa classe tra quelle per il Profile:

<profile defaultProvider="AspNetAccessProvider">
 <properties>
  <add name="MiaClasse" serializeAs="Binary" type="MiaClasse" />
 </properties>
...

All'avvio sembra tutto corretto, ma questa classe non viene memorizzata. Ogni volta che tento l'accesso alla propietà "MiaClasse" della classe "Profile", ottengo sempre un oggetto nuovo. Ma perché questo? Con tipi stringa, DataTable e altri nessun problema, ma con la mia classe nulla... Per cercare di capire la causa di questo mistero - e per imparare qualcosa di nuovo - decido di scrivermi il mio provider per il Profile. Scrivo la mia bella classe ereditandola da "ProfileProvider", faccio l'override dei method a me utili ("SetPropertyValues", "GetPropertyValues" e altre), prendo gli oggetti inseriti da codice nel profile e inserisco del codice per la serializzazione personalizzata che, per la cronaca, è su file. Niente di complesso il codice:

string filename = "...";
MiaClasse mc=ppvc["MiaClasse"].PropertyValue as MiaClasse;
BinaryFormatter formatter = new BinaryFormatter();
using (FileStream file = new FileStream(filename, FileMode.Create, FileAccess.Write))
{
    // Effettuo la serializzazione
    formatter.Serialize(file, mc);
}

Quindi per la deserializzazione:

string filename = "...";
MiaClasse mc=null;
BinaryFormatter formatter = new BinaryFormatter();
// Apro in lettura il file
using (FileStream file = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
    mc = formatter.Deserialize(file) as MiaClasse;
}

Provo il codice, ma se per la serializzazione tutto funziona perfettamente, al tentativo di deserializzazione ottengo l'errore:

"The constructor to deserialize an object of type MiaClasse was not found."

Cioè? Penso di avere sbagliato qualcosa nel codice per la deserializzazione, provo con tipi stringa, DataTable e così via... ma non riscontro nessun problema. In quel momento inizio a pensare che i tipi Generic non possono essere deserializzati, ma se possono essere serializzati perché non potrebbero? Faccio delle prove direttamente con un tipo Generic:

string filename = "...";
Dictionary<int,int> mc=new Dictionary<int,int>();
MiaClasse.Add(1,1);
BinaryFormatter formatter = new BinaryFormatter();
using (FileStream file = new FileStream(filename, FileMode.Create, FileAccess.Write))
{
formatter.Serialize(file, mc);
}

Quindi per la deserializzazione:

string filename = "...";
Directory<int,int> mc=null;
BinaryFormatter formatter = new BinaryFormatter();
using (FileStream file = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
mc = formatter.Deserialize(file) as Directory<int,int>;
}

Testo il codice e tutto funziona! Ma come? Mi convinco di aver di fronte un'assurdità data dal Framework nella Beta 1: è possibile serializzare un tipo generic ma non posso usarlo nel profile... e per usare il generic devo utilizzarlo in una classe ereditata da un generic, ma questo non può essere serializzato... il Framework mi sta prendendo in giro? Prima di rinunciare e tornare a vivere, torno sull'argomento del costruttore per la deserializzazione non trovato (si ricorda quell'errore?). Alla fine mi accorgo di un altro mio limite nella conoscenza dei meandri del Framework. Guardando con il Reflector la classe Dictionary e altre, trovo il costruttore:

protected Dictionary(SerializationInfo info, StreamingContext context);

Mi rendo conto della sciocchezza. Modifico la classe "MiaClasse" in questo modo:

[Serializable]
public class MiaClasse : Dictionary<int, int>
{
 public MiaClasse(SerializationInfo info, StreamingContext context) : base(info, context)
    { }
 public MiaClasse() : base()
 { }
}

Riavvio il tutto e sia con la memorizzazione con il Provider su Access, sia con il mio personalizzato tutto funziona. Non si finisce mai di imparare... com'era quella frase? E il naufragar m'è dolce in questo mare... E' Leopardi l'autore? Mah...

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Nella stessa categoria
I più letti del mese