2015-04-03 7 views
9

Die .NET BinaryReader/BinaryWriter Klassen können unter Angabe eines Encoding für String-bezogene Operationen erstellt werden.Get Encoding von BinaryReader/Writer?

Ich habe benutzerdefinierte String-Formate mit Erweiterungsmethoden implementiert, würde sie aber dennoch so implementieren, dass sie die Encoding, die beim Instanziieren des BinaryReader/Writer angegeben wurde, respektieren.

Es scheint keine Möglichkeit zu geben, die Codierung vom Leser/Schreiber abzurufen, nicht einmal beim Erben von ihrer Klasse. Ich konnte nur von ihnen erben, um die übergebene Codierung abzufangen, indem sie alle ihre Konstruktoren neu erstellte. Ich schaute in die .NET source code, und es wird nur verwendet, um eine Decoder-Klasse (im Falle der BinaryReader) zu instanziieren, aber ich kann auch nicht darauf zugreifen.

Verliere ich zu einem Mangel in diesen Klassen hier? Kann ich mit Reflexion in sie hacken?

+0

OK, Sie haben Recht. Die WriteString-Methode scheint dies jedoch explizit zu ignorieren (laut MSDN). –

+1

Wenn das Unterklassieren und Abfangen der Kodierung in den Konstruktoren in Ihrem Szenario auch nur entfernt möglich ist, würde ich es vor potenziell instabilen Reflexions-Hacks bevorzugen.(Was ich nicht sicher bin, ist sogar möglich, da ich keine Codierungsreferenz in der Decoder-Klasse sah.) – nodots

+0

Können Sie erklären, warum Ihre Erweiterungsmethoden auf dem BinaryReader/BinaryWriter selbst funktionieren müssen? Die ReadString/WriteString-Methoden sollten die Kodierung übersetzen. Wenn also Ihre Erweiterungsmethoden die Strings verwenden, die bei diesen Methoden ein- und ausgehen, scheint es mir, als müssten Sie sich keine Gedanken darüber machen? –

Antwort

3

Wenn Subclassing und Abfangen der Codierung in den Konstruktoren in Ihrem Szenario auch nur entfernt möglich ist, würde ich es vor potenziell instabilen Reflektionshacken bevorzugen.

Wenn Sie jedoch müssen die Reflexion Route aus irgendeinem Grund gehen, hier sind einige Hinweise, die ich von the BinaryReader source code you referenced gefunden:

+1

Ich ging mit dem Konstruktor Ansatz. Zum Glück haben sie nur 3 öffentliche Konstrukteure. Denken Sie daran, 'new UTF8Encoding()' für den Standardfall zu beachten, für den keine Kodierung angegeben wurde. –

5

Mit Blick auf die source code for BinaryReader, sehe ich der Konstruktor wird wie folgt definiert:

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"); 
    } 

So sieht es aus wie die Codierung selbst nicht eigentlich überall zurückgehalten wird. Die Klasse speichert nur einen Decoder, der von der Codierung abgeleitet ist. m_decoder ist definiert als in der Klasse folgt:

private Decoder m_decoder; 

Sie können nicht die privaten Variable zugreifen. Eine Suche nach dieser Variable im Rest der Klasse zeigt, dass sie intern an einigen Stellen verwendet wird, aber nie zurückgegeben wird. Ich denke also nicht, dass Sie irgendwo in Ihrer abgeleiteten Klasse darauf zugreifen können, ohne irgendeine verrückte Sache zu machen . Es müsste als protected definiert werden, damit Sie darauf zugreifen können. Es tut uns leid.

Edit:

Es ist mit ziemlicher Sicherheit ein besserer Weg, um Ihr Problem zu lösen als Reflexion mit den privaten m_decoder Variable zuzugreifen. Und selbst wenn Sie das tun, könnte es Ihnen nicht die Kodierung bringen, wie Sie in den Kommentaren notiert haben. Wenn Sie es dennoch trotzdem tun möchten, lesen Sie this StackOverflow answer on how to access private members with reflection.

+0

Außerdem glaube ich nicht, dass es möglich ist, die Codierung vom Decoder zurück zu bekommen, zumindest von dem, was ich beim Scrollen durch die Quelle gelesen habe. –