Если вы хотите, чтобы ваш пользовательский StreamReader мог использоваться везде, где можно использовать TextReader, обычно есть два варианта.
Наследуйте от StreamReader и переопределяйте функции, которые вы хотите, чтобы они работали по-другому. В вашем случае это будет StreamReader.ReadLine.
Наследуйте от TextReader и полностью реализуйте функциональность считывателя в соответствии с вашими требованиями.
Примечание: для варианта 2 выше вы можете сохранить внутреннюю ссылку на экземпляр StreamReader и делегировать все функции внутреннему экземпляру, кроме части функциональности, которую вы хотите заменить. На мой взгляд, это просто детали реализации варианта 2, а не третьего варианта.
Исходя из вашего вопроса, я предполагаю, что вы пробовали вариант 1 и обнаружили, что переопределение StreamReader.ReadLine довольно сложно, поскольку вы не можете получить доступ к внутренним компонентам класса. Хорошо, что для StreamReader вам повезло, и вы можете достичь этого, не имея доступа к внутренней реализации StreamReader.
Вот простой пример:
Отказ от ответственности: реализация ReadLine()
предназначена для демонстрационных целей и не предназначена для надежной или полной реализации.
class CustomStreamReader : StreamReader
{
public CustomStreamReader(Stream stream)
: base(stream)
{
}
public override string ReadLine()
{
int c;
c = Read();
if (c == -1)
{
return null;
}
StringBuilder sb = new StringBuilder();
do
{
char ch = (char)c;
if (ch == ',')
{
return sb.ToString();
}
else
{
sb.Append(ch);
}
} while ((c = Read()) != -1);
return sb.ToString();
}
}
Вы заметите, что я просто использовал метод StreamReader.Read () для чтения символов из потока. Хотя метод Read()
определенно меньше по формуле, чем работа напрямую с внутренними буферами, он все же использует внутреннюю буферизацию, поэтому все равно должен давать довольно хорошую производительность, но это следует проверить, чтобы подтвердить.
Для забавы, вот пример варианта 2. Я использовал инкапсулированный StreamReader, чтобы уменьшить реальный код, это вообще не проверялось.
class EncapsulatedReader : TextReader
{
private StreamReader _reader;
public EncapsulatedReader(Stream stream)
{
_reader = new StreamReader(stream);
}
public Stream BaseStream
{
get
{
return _reader.BaseStream;
}
}
public override string ReadLine()
{
int c;
c = Read();
if (c == -1)
{
return null;
}
StringBuilder sb = new StringBuilder();
do
{
char ch = (char)c;
if (ch == ',')
{
return sb.ToString();
}
else
{
sb.Append(ch);
}
} while ((c = Read()) != -1);
return sb.ToString();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_reader.Close();
}
base.Dispose(disposing);
}
public override int Peek()
{
return _reader.Peek();
}
public override int Read()
{
return _reader.Read();
}
public override int Read(char[] buffer, int index, int count)
{
return _reader.Read(buffer, index, count);
}
public override int ReadBlock(char[] buffer, int index, int count)
{
return _reader.ReadBlock(buffer, index, count);
}
public override string ReadToEnd()
{
return _reader.ReadToEnd();
}
public override void Close()
{
_reader.Close();
base.Close();
}
}