Получить кодировку BinaryReader/Writer?
Сеть BinaryReader/BinaryWriter
классы могут быть построены с указанием Encoding
использовать для String
связанные операции.
Я реализовывал пользовательские форматы строк с помощью методов расширения, но все же реализовывал их так, чтобы они уважали Encoding
указывается при создании экземпляра BinaryReader/Writer
,
Кажется, что нет способа извлечь кодировку из устройства чтения / записи, даже при наследовании от их класса. Я мог только унаследовать их, чтобы перехватить переданную кодировку, воссоздав все их конструкторы. Я посмотрел на исходный код.NET, и он используется только для создания экземпляра класса Decoder (в случае BinaryReader
), но я тоже не могу получить к нему доступ.
Я проигрываю с недостатком в этих классах здесь? Могу ли я взломать их с отражением?
2 ответа
Если подклассы и перехват Encoding в конструкторах даже отдаленно возможны в вашем сценарии, я бы предпочел это вместо потенциально нестабильных взломов отражения.
Однако, если вы по какой-то причине должны пойти по пути отражения, вот несколько указателей, которые я нашел в исходном коде BinaryReader, на который вы ссылались:
-
Decoder
Сам класс, по-видимому, не имеет никакого отношения кEncoding
но: -
Decoder
экземпляр создается путем вызоваencoding.GetDecoder()
(строка 65) - Который возвращает экземпляр внутреннего класса
DefaultDecoder
- Который держит
Encoding
вm_encoding
Глядя на исходный код BinaryReader, я вижу, что конструктор определяется следующим образом:
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");
}
Похоже, что сама кодировка нигде не сохраняется. Класс просто хранит декодер, полученный из кодировки. m_decoder
определяется следующим образом в классе:
private Decoder m_decoder;
Вы не можете получить доступ к закрытой переменной. Поиск этой переменной в остальной части класса показывает, что она используется в нескольких местах внутри, но никогда не возвращается, поэтому я не думаю, что вы можете получить к ней доступ в любом месте вашего производного класса без каких-либо сумасшедших размышлений / разборок, Это должно быть определено как protected
для вас, чтобы получить к нему доступ. Сожалею.
Редактировать:
Существует почти наверняка лучший способ решить вашу проблему, чем использовать отражение для доступа к частному m_decoder
переменная. И даже если вы это сделали, это может не дать вам кодировку, как вы отметили в комментариях. Однако, если вы все равно хотите это сделать, посмотрите ответ Stackru о том, как получить доступ к закрытым членам с помощью отражения.