2015-04-03 12 views
9

Le classi .NET BinaryReader/BinaryWriter possono essere costruite specificando un Encoding da utilizzare per le operazioni relative a String.Ottieni la codifica di BinaryReader/Writer?

Stavo implementando formati di stringa personalizzati con i metodi di estensione, ma li implementerei comunque in un modo che rispettano lo Encoding specificato durante l'istanziazione dello BinaryReader/Writer.

Non sembra essere un modo per recuperare la codifica dal lettore/scrittore, nemmeno quando si eredita dalla loro classe. Potevo solo ereditare da loro per intercettare la codifica passata ricreando tutti i loro costruttori. Ho esaminato lo .NET source code ed è usato solo per istanziare una classe Decoder (nel caso dello BinaryReader), ma non riesco ad accedere anche a quello.

Perdo in una di quelle classi qui? Posso inserirli con la riflessione?

+0

OK, hai ragione. Il metodo WriteString sembra ignorarlo esplicitamente (secondo MSDN). –

+1

Se la sottoclasse e l'intercettazione della codifica nei costruttori è anche lontanamente fattibile nel tuo scenario, preferirei gli hack di riflessione potenzialmente instabili.(Che non sono sicuro sono possibili anche perché non ho visto alcun riferimento alla codifica nella classe Decoder.) – nodots

+0

Puoi spiegare perché i tuoi metodi di estensione devono operare su BinaryReader/BinaryWriter? I metodi ReadString/WriteString dovrebbero tradurre la codifica, quindi se i tuoi metodi di estensione operano sulle stringhe che entrano ed escono da questi metodi, mi sembra che non dovresti preoccuparti di ciò? –

risposta

3

Se la sottoclasse e l'intercettazione della codifica nei costruttori è anche lontanamente fattibile nel tuo scenario, preferirei gli hack di riflessione potenzialmente instabili.

Tuttavia, se si necessario andare il percorso di riflessione, per qualche motivo, qui ci sono alcune indicazioni che ho trovato da the BinaryReader source code you referenced:

+1

Sono andato con l'approccio del costruttore. Fortunatamente hanno solo 3 costruttori pubblici. Assicurati di ricordare 'new UTF8Encoding()' per il caso predefinito in cui non è stata specificata alcuna codifica. –

5

Guardando il source code for BinaryReader, vedo il costruttore è definito come segue:

public BinaryReader(Stream input, Encoding encoding, bool leaveOpen) { 
     if (input==null) { 
      throw new ArgumentNullException("input"); 
     } 
     if (encoding==null) { 
      throw new ArgumentNullException("encoding"); 
     } 
     if (!input.CanRead) 
      throw new ArgumentException(Environment.GetResourceString("Argument_StreamNotReadable")); 
     Contract.EndContractBlock(); 
     m_stream = input; 
     m_decoder = encoding.GetDecoder(); 
     m_maxCharsSize = encoding.GetMaxCharCount(MaxCharBytesSize); 
     int minBufferSize = encoding.GetMaxByteCount(1); // max bytes per one char 
     if (minBufferSize < 16) 
      minBufferSize = 16; 
     m_buffer = new byte[minBufferSize]; 
     // m_charBuffer and m_charBytes will be left null. 

     // For Encodings that always use 2 bytes per char (or more), 
     // special case them here to make Read() & Peek() faster. 
     m_2BytesPerChar = encoding is UnicodeEncoding; 
     // check if BinaryReader is based on MemoryStream, and keep this for it's life 
     // we cannot use "as" operator, since derived classes are not allowed 
     m_isMemoryStream = (m_stream.GetType() == typeof(MemoryStream)); 
     m_leaveOpen = leaveOpen; 

     Contract.Assert(m_decoder!=null, "[BinaryReader.ctor]m_decoder!=null"); 
    } 

modo che appaia come la codifica in sé non è in realtà mantenuto ovunque. La classe memorizza solo un decodificatore derivato dalla codifica. m_decoder è definito come segue nella classe:

private Decoder m_decoder; 

Non è possibile accedere alla variabile privata. Fare una ricerca per quella variabile nel resto della classe mostra che è usato internamente in alcuni posti, ma non viene mai restituito, quindi non penso che tu possa accedervi da nessuna parte nella tua classe derivata senza fare una specie di pazzo oggetto di riflessione/smontaggio . Dovrebbe essere definito come protected per poterlo accedere. Scusate.

Edit:

C'è quasi certamente un modo migliore per risolvere il problema di usare riflessione per accedere al m_decoder variabile privata. E anche se lo facessi, potrebbe non ottenere la codifica, come hai notato nei commenti. Tuttavia, se si desidera comunque farlo comunque, vedere this StackOverflow answer on how to access private members with reflection.

+0

Inoltre, non penso sia possibile recuperare la codifica dal decodificatore, almeno da ciò che ho letto durante lo scorrimento della sorgente. –