tl; dr
Suggerisco metodi statici, o anche i metodi di istanza possono essere validi a seconda degli oggetti con cui lavori e di quanto tempo sono vissuti, nonché di quanto siano statici.
Non usa le proprietà per questo. Le proprietà dovrebbero essere il più identi- ficabili possibile (l'accesso ripetuto dovrebbe restituire costantemente lo stesso risultato). Se una proprietà ha bisogno di eseguire la logica per divinarne lo stato, non è sempre terribile, ma le proprietà non dovrebbero mai essere che modificano lo stato in Get
.
Di solito quando si ha a che fare con un insieme di dati sottostante per deserializzare qualcosa si avrà una posizione corrente in quel set, e l'atto di deserializzazione sposterà quella posizione causando così un Get
di cambiare stato.
Una volta ho scritto un po 'di serializzazione binaria per alcuni oggetti semplici che avevamo, e ho trovato molto utile semplicemente creare i metodi di estensione dei metodi sulle classi BinaryReader
e BinaryWriter
. Se osservi queste classi, hanno già metodi per trasformare dati binari in tipi di dati con ReadInt
e ReadString
ecc, quindi i metodi statici si basano su questi per ricostruire gli oggetti.
È come tale:
public class FunnyAnimal
{
public int NumberOfLegs { get; set; }
public string Name { get; set; }
public Tuple<int, int> EarHearingSensitivity { get; set; }
}
public static class BinaryWriterExtensions
{
public FunnyAnimal WriteFunnyAnimal(this BinaryWriter writer, FunnyAnimal animalToBeWritten)
{
writer.WriteInt(animalToBeWritten.NumberOfLegs);
writer.WrinteString(animalToBeWritten.Name);
writer.WriteInt(animalToBeWritten.EarHearingSensitivity.Item1);
writer.WriteInt(animalToBeWritten.EarHearingSensitivity.Item2);
}
}
public static class BinaryReaderExtensions
{
public FunnyAnimal ReadFunnyAnimal(this BinaryReader reader)
{
return new FunnyAnimal()
{
NumberOfLegs = reader.ReadInt(),
Name = reader.ReadString(),
EarHearingSensitivity = Tuple.Create(reader.ReadInt(), reader.ReadInt())
};
}
}
Quindi l'uso è:
//To write it out to a stream
using (var writer = new BinaryWriter(someUnderlyingStreamToWriteTo))
{
writer.WriteFunnyAnimal(yourFunnyAnimalObject);
}
//To read it in from a stream
FunnyAnimal deserializedFunnyAnimal = null;
using (var reader = new BinaryReader(someUnderlyingStreamToReadFrom))
{
deserializedFunnyAnimal = reader.ReadFunnyAnimal();
}
Lo stesso approccio potrebbe essere applicato a qualsiasi tipo di serializzatore con cui stai lavorando, se stai usando semplicemente BinaryFormatter
puoi creare le tue estensioni su MemoryStream
e fare in modo che i metodi utilizzino un BinaryFormatter
per leggi e scrivi dallo stream, ma l'uso è chiaro e semplice, costruisci MemoryStream
e ReadFunnyAnimal
o WriteFunnyAnimal
su di esso, ei metodi di estensione creeranno e gestiranno BinaryFormatter
Ultimi pensieri
Quando si ha a che fare con la serializzazione binaria / deserializzazione, troverete il flusso più conveniente sottostante molte volte potrebbe essere solo un MemoryStream con un array che lo supporta in modo da poter afferrare l'array di byte quando hai finito, a meno che tu non abbia un file o altra risorsa su cui stai specificando la serializzazione.
Se all'interno hai bisogno di oggetti complessi che richiedono la serializzazione, questa tecnica è utile perché l'implementazione per le estensioni writer e reader avrà accesso al lettore / scrittore in modo che anche i metodi di estensione per i tuoi oggetti complessi incorporati siano nello scopo di essere usato come:
return new FunnyAnimal() { ComplexTailMember = reader.ReadTail(); }
Inoltre vale la pena riconoscere quando si tratta di implementazioni di serializzazione / deserializzazione che avranno il proprietario del flusso. Le tue estensioni non dovrebbero possederle, nel senso che non dovrebbero aprirle / spostarle / eliminarle dopo averle terminate, piuttosto che dovrebbero essere di proprietà del codice che crea il lettore / scrittore, quindi regola il pollice con stream e streamreader / writer:
Se il tuo Stream
/ StreamReader
/ StreamWriter
sono parametri del tuo metodo, non dovresti eliminarli. Se crei il Stream
, è tua responsabilità eliminarlo.
L'unico sniglet a cui fare attenzione è che a volte il metodo di smaltimento di StreamReader / StreamWriter disporrà dello stream sottostante, ma attenzione che non si dispone del lettore / scrittore prima che il flusso sia completo.