La serializzazione viene eseguita meglio nei metodi di istanza o nei metodi statici

3

Dire che ho una classe workStockItem , che desidero serializzare.

Qual è lo stile migliore?

  1. utilizzando un metodo statico

    o

  2. utilizzando un metodo non statico (forse anche implementato come una proprietà come visto di seguito)

Implementazioni di esempio:

internal static byte[] serialiaze(workStockItem toSer)
    {
        IFormatter formatter = new BinaryFormatter();
        MemoryStream stream = new MemoryStream();
        formatter.Serialize(stream, toSer);
        return stream.ToArray();
    }

internal byte[] binaryRepresentation
    {
        get
        {
            IFormatter formatter = new BinaryFormatter();
            MemoryStream stream = new MemoryStream();
            formatter.Serialize(stream, this);
            return stream.ToArray();
        }
    }

Anche in questo caso:
Qual è lo stile migliore e perché?

    
posta Mark 04.07.2014 - 08:54
fonte

1 risposta

5

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.

    
risposta data 04.07.2014 - 10:06
fonte

Leggi altre domande sui tag