Domanda

Ho 3 TextReaders - una combinazione di StreamReaders e StringReaders. Concettualmente, la concatenazione di loro è un singolo documento di testo.

Voglio chiamare un metodo (non sotto il mio controllo) che prende un singolo TextReader. C'è un modo integrato o facile fare un TextReader concatenazione da più TextReaders?

(I potrebbero scrivere il mio sottoclasse TextReader, ma sembra una buona dose di lavoro. In tal caso, avevo appena li scrivo in un file temporaneo e quindi aprirlo con un singolo StreamReader.)

C'è una soluzione facile per questo che mi manca?

È stato utile?

Soluzione

Ho appena buttato questo insieme, quindi non è super-robusta (senza gestione degli errori, ecc), ma il banco di prova di base funziona.

Funziona con la creazione di un metodo di estensione per di TextReader che prendono un secondo, e restituisce una nuova classe TextReader che chiama internamente Read() al primo fino a quando non si esaurisce, e poi inizia a chiamare Read()on il secondo. È possibile concatenare questo tempo indeterminato.

Per fornire una completa implementazione di TextReader avete solo bisogno di implementare Read(), Peek(), Close() e Dispose(). Tutti gli altri metodi si basano sulla specifica Read() implementazione al lavoro. Quindi creare il proprio TextReader in realtà non è così male, come si può vedere qui sotto.

Questo allevia anche eventuali problemi di prestazioni dal momento che stiamo semplicemente avvolgendo il TextReaders esistenti e non effettivamente invocando loro di eseguire la concatenazione.

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();
            }
        }
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top