Frage

Ich habe 3 TextReaders - eine Kombination aus StreamReaders und StringReaders. Konzeptionell ist die Verkettung von ihnen ist ein Textdokument.

Ich möchte eine Methode aufrufen (nicht unter meiner Kontrolle), die einen einzelnen Textreader nimmt. Gibt es eine eingebaute oder einfache Möglichkeit, eine Verkettung von mehreren Textreader TextReaders zu machen?

(I könnte Eigene Textreader Unterklasse schreiben, aber es sieht aus wie eine Menge Arbeit. In diesem Fall würde ich sie nur schreiben alle in eine temporäre Datei und dann öffnen mit eine einzige Stream.)

Gibt es eine einfache Lösung für dieses Problem, dass ich fehlte?

War es hilfreich?

Lösung

Ich habe gerade wirft diese zusammen, so ist es nicht super-robust (keine Fehlerbehandlung, etc.), aber der grundlegenden Testfall funktioniert.

Es funktioniert durch eine Erweiterungsmethode für TextReader die zu schaffen, die eine zweite nehmen, und gibt eine neue Klasse Textreader, die intern Read() auf der ersten Anrufe, bis er abgelaufen ist, und beginnt dann Read()on Aufruf der zweite. Sie können die Kette dieses auf unbestimmte Zeit.

Um eine vollständige Umsetzung der TextReader Sie brauchen nur Read(), Peek(), Close() und Dispose() zu implementieren. Alle anderen Methoden beruhen auf spezifischen Implementierung Read() an die Arbeit. So die Schaffung wirklich Ihr eigenes TextReader nicht so schlecht, wie Sie unten sehen können.

Dies erleichtert auch keine Leistungsprobleme, weil wir einfach die vorhandenen TextReaders wickeln und nicht eigentlich sie Berufung auf die Verkettung auszuführen.

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();
            }
        }
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top