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

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

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

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

Есть ли простое решение, которое мне не хватает?


person Ken    schedule 27.05.2010    source источник


Ответы (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();
            }
        }
    }
}
person Rex M    schedule 27.05.2010
comment
О, это умно: обрабатывать только 2 и использовать метод расширения, чтобы связать их. - person Ken; 28.05.2010