Как связать несколько TextReader вместе?

У меня есть 3 TextReaders - комбинация StreamReaders и StringReaders. Концептуально их объединение представляет собой единый текстовый документ.

Я хочу вызвать метод (не под моим контролем), который принимает один TextReader. Есть ли какой-либо встроенный или простой способ сделать сцепление TextReader из нескольких TextReader?

мог бы написать свой собственный подкласс TextReader, но это выглядит довольно трудоемко. В этом случае я бы просто записал их все во временный файл, а затем открыл его одним StreamReader.)

Есть ли простое решение, которое я пропускаю?

1 ответ

Решение

Я просто скомбинировал это, так что это не супер-надежно (без обработки ошибок и т. Д.), Но базовый тестовый пример работает.

Он работает путем создания метода расширения для TextReader, которые занимают секунду, и возвращает новый класс TextReader, который внутренне вызывает Read() на первом пока не кончится, а потом начинает звонить Read()На втором. Вы можете связать это на неопределенный срок.

Для обеспечения полной реализации TextReader вам нужно только реализовать Read(), Peek(), Close() а также Dispose(), Все остальные методы зависят от конкретной реализации. Read() работать. Так что создавая свой TextReader на самом деле не все так плохо, как вы можете видеть ниже.

Это также устраняет любые проблемы с производительностью, поскольку мы просто оборачиваем существующие TextReaders и фактически не вызываем их для выполнения конкатенации.

class Program
{
    static void Main(string[] args)
    {
        StringReader first = new StringReader("hello ");
        StringReader second = new StringReader("world");
        StringReader third = new StringReader("!");

        using (var allOfThem = first.Concat(second).Concat(third))
        {
            //writes "hello world!"
            Console.WriteLine(allOfThem.ReadToEnd());
        }
        Console.Read();
    }
}

public static class Extensions
{
    public static TextReader Concat(this TextReader first, TextReader second)
    {
        return new ChainedTextReader(first, second);
    }

    private class ChainedTextReader : TextReader
    {
        private TextReader first;
        private TextReader second;
        private bool readFirst = true;

        public ChainedTextReader(TextReader first, TextReader second)
        {
            this.first = first;
            this.second = second;
        }

        public override int Peek()
        {
            if (readFirst)
            {
                return first.Peek();
            }
            else
            {
                return second.Peek();
            }
        }

        public override int Read()
        {
            if (readFirst)
            {
                int value = first.Read();
                if (value == -1)
                {
                    readFirst = false;
                }
                else
                {
                    return value;
                }
            }
            return second.Read();
        }

        public override void Close()
        {
            first.Close();
            second.Close();
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            if (disposing)
            {
                first.Dispose();
                second.Dispose();
            }
        }
    }
}
Другие вопросы по тегам