Question

J'ai 3 TextReaders - une combinaison de StreamReaders et StringReaders. Conceptuellement, la concaténation d'entre eux est un document de texte.

Je veux appeler une méthode (pas sous mon contrôle) qui prend un seul TextReader. Est-il possible intégré ou facile de faire une TextReader de concaténer plusieurs TextReaders?

(I peut écrire mon propre sous-classe TextReader, mais il ressemble à un montant juste du travail. Dans ce cas, je venais de les écrire tous vers un fichier temporaire, puis ouvrez-le avec un seul StreamReader.)

Y at-il une solution facile à ce que je suis absent?

Était-ce utile?

La solution

Je viens de jeter cela ensemble, il est donc pas super robuste (pas de traitement d'erreur, etc.) mais les travaux cas de test de base.

Il fonctionne en créant une méthode d'extension pour son de TextReader qui prennent une seconde et retourne une nouvelle classe TextReader qui appelle en interne Read() le premier jusqu'à ce qu'il épuise, puis commence à appeler Read()on la seconde. Vous pouvez enchaîner indéfiniment.

Fournir une mise en œuvre complète de TextReader il vous suffit de mettre en œuvre Read(), Peek(), Close() et Dispose(). Toutes les autres méthodes reposent sur Read() de mise en œuvre spécifique au travail. Ainsi, la création de votre propre TextReader est vraiment pas si mal, comme vous pouvez le voir ci-dessous.

Ceci évite également les problèmes de performance puisque nous terminons simplement les TextReaders existants et ne pas les invoquer en fait pour effectuer la concaténation.

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();
            }
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top