Search code examples
.neteventsstringwritertextwriter

Is there a TextWriter child class that fires event if text is written?


I have written a method that accepts a TextWriter as an argument (Usually Console.Out, but not necessarily).

When I call this method, some progress info is written to the TextWriter. However, since this method can run a long time, I want to update my UI with some status information.

Currently, I am using a StringWriter but it does not have any events. So the first time I get a result from the StringWriter is after the method completed.

Now I am searching for a class that inherits from TextWriter and fires an TextChanged event or something like that. I know that this shouldn't be to hard to implement, but I bet the CLR Team already did it for me, I just can't find the appropriate class.


Solution

  • If anyone is interested, this is a class that extends the StringWriter() class to fire events after every call to writer.Flush().

    I also added the posibillity to automatically call Flush() after every write, since, in my case, a third party component, that did write to the console, didn't do a flush.

    Sample usage:

    void DoIt()
    {
        var writer = new StringWriterExt(true); // true = AutoFlush
        writer.Flushed += new StringWriterExt.FlushedEventHandler(writer_Flushed);
    
        TextWriter stdout = Console.Out;
        try
        {
            Console.SetOut(writer);
            CallLongRunningMethodThatDumpsInfoOnConsole();
        }
        finally
        {
            Console.SetOut(stdout);
        }
    }
    

    Now I can display some status information just in time and don't need to wait for the method to finish.

    void writer_Flushed(object sender, EventArgs args)
    {
        UpdateUi(sender.ToString());
    }
    

    And here is the class:

    public class StringWriterExt : StringWriter
    {
        [EditorBrowsable(EditorBrowsableState.Never)]
        public delegate void FlushedEventHandler(object sender, EventArgs args);
        public event FlushedEventHandler Flushed;
        public virtual bool AutoFlush { get; set; }
    
        public StringWriterExt()
            : base() { }
    
        public StringWriterExt(bool autoFlush)
            : base() { this.AutoFlush = autoFlush; }
    
        protected void OnFlush()
        {
            var eh = Flushed;
            if (eh != null)
                eh(this, EventArgs.Empty);
        }
    
        public override void Flush()
        {
            base.Flush();
            OnFlush();
        }
    
        public override void Write(char value)
        {
            base.Write(value);
            if (AutoFlush) Flush();
        }
    
        public override void Write(string value)
        {
            base.Write(value);
            if (AutoFlush) Flush();
        }
    
        public override void Write(char[] buffer, int index, int count)
        {
            base.Write(buffer, index, count);
            if (AutoFlush) Flush();
        }
    }