【问题标题】:Implementing a Derived Class of TextWriter实现 TextWriter 的派生类
【发布时间】:2013-07-18 00:35:53
【问题描述】:

我有两个课程,我无法以任何方式更改它们:

类 1:将TextWriter 作为构造函数参数并将其用作输出流。

类 2:提供方法WriteLine(string)

我需要一个适配器,以便将 Class1 的所有输出写入 Class2。因此,我启动了一个扩展 TextWriter 并缓冲传入文本的适配器,一旦有新行到达,就会将其刷新到 class2 实例。

但是,TextWriter 中有许多越来越多的方法——我应该实现哪些? Class1 中的输出仅为字符串。

根据 MSDN,至少应该覆盖 Write(char),但是,这会强制我自己处理所有 \r\n 新行...

Q1:您知道实现目标的更好方法吗? Q2:如果不是,我应该重写哪些 TextWriter 方法以最小化实现工作。

【问题讨论】:

    标签: c# textwriter


    【解决方案1】:

    在您的TextWriter 派生类上实现Write(char) 就是您需要做的所有事情。如果有人在您的新类上调用WriteLine,则会调用基类WriteLine 方法。它会做正确的事:使用单独的 \r\n 字符调用您的 Write 方法。

    实际上,WriteLine(string) 看起来像这样:

    void WriteLine(string s)
    {
        Write(s);
        Write("\r\n");
    }
    

    Write(string) 实际上是:

    foreach (char c in s)
    {
        Write(c);
    }
    

    TextWriter 中的所有 Write 方法都解析为在循环中调用 Write(char) 的东西。

    您真的不必执行任何其他操作。只需覆盖Write(char) 并将其插入即可。它会起作用。

    可以覆盖那些其他方法。这样做会让你的课堂更有效率(更快)。但这不是必需的。我说做你能做的最简单的事情。然后,如果您在分析后确定您的自定义编写器太慢,请根据需要覆盖其他方法。

    这是一个最小的TextWriter后代:

    public class ConsoleTextWriter: TextWriter
    {
        public override void Write(char value)
        {
            Console.Write(value);
        }
    
        public override Encoding Encoding
        {
            get { return Encoding.Default; }
        }
    }
    

    如果我接着写:

    using (var myWriter = new ConsoleTextWriter())
    {
        myWriter.Write("hello, world");
        myWriter.WriteLine();
        myWriter.WriteLine();
        myWriter.WriteLine("Goodbye cruel world.");
        myWriter.Write("Fee fie foe foo!");
    }
    

    输出是:

    hello, world
    
    Goodbye cruel world.
    Fee fie foe foo!
    

    【讨论】:

    • 感谢您的回答,但是,我什么时候知道什么时候可以通过 WriteLine() 将其刷新到底层 2 类?我只能在“全线”中做到这一点。例如。我必须在 Write(char) 中寻找 NewLines? \n 是换行符吗? \r\n?也许在不同的平台上有别的东西?
    • “你可以重写那些其他方法。这样做会让你的类更高效(更快)”你是指哪些方法?仅覆盖 Write(char) 会导致打印速度非常慢。
    • @Protectorone:重写几乎任何虚拟方法都会提高性能。你是对的,最小的实现——仅覆盖Write(char)——导致打印速度非常慢。但它有效,这是一件非常方便的事情。
    • @bikeman868: WriteLine(string) 填充字符缓冲区并调用Write(Char[], int buffer, int count),然后循环调用Write(Char)。见referencesource.microsoft.com/#mscorlib/system/io/…。我很确定一直都是这样,但我可能弄错了。
    • 在 Visual Studio 中按 F12 并查看反编译的源代码。 WriteLine 很明显在当前版本的 .Net 4.0 中没有使用 Write(Char)。
    【解决方案2】:

    我正在添加另一个答案,因为我无法让上述答案起作用!

    根据我的经验,我必须覆盖 WriteLine()WriteLine(string) 才能使这些功能起作用。

    这是一个示例,可用于在长时间运行的任务中编写网页。顺便说一句,HttpResponse 对象来自 ASP.net MVC。

    public class WebConsoleWriter : TextWriter
    {
        HttpResponseBase Response { get; set; }
        bool FlushAfterEveryWrite { get; set; }
        bool AutoScrollToBottom { get; set; }
        Color BackgroundColor { get; set; }
        Color TextColor { get; set; }
    
        public WebConsoleWriter(HttpResponseBase response, bool flushAfterEveryWrite, bool autoScrollToBottom)
        {
            Response = response;
            FlushAfterEveryWrite = flushAfterEveryWrite;
            AutoScrollToBottom = autoScrollToBottom;
            BackgroundColor = Color.White;
            TextColor = Color.Black;
        }
    
        public WebConsoleWriter(HttpResponseBase response, bool flushAfterEveryWrite,  bool autoScrollToBottom, Color backgroundColor, Color textColor)
        {
            Response = response;
            FlushAfterEveryWrite = flushAfterEveryWrite;
            AutoScrollToBottom = autoScrollToBottom;
            BackgroundColor = backgroundColor;
            TextColor = textColor;
        }
    
        public virtual void WritePageBeforeStreamingText()
        {
            string headerFormat =
    @"<!DOCTYPE html>
    <html>
    <head>
        <title>Web Console</title>
        <style>
            html {{
                background-color: {0};
                color: {1};
            }}
        </style>        
    </head>
    <body><pre>";
            string backgroundColorHex = ColorTranslator.ToHtml(BackgroundColor);
            string foregroundColorHex = ColorTranslator.ToHtml(TextColor);
            Response.Write(string.Format(headerFormat, backgroundColorHex, foregroundColorHex));
    
            // Add a 256 byte comment because I read that some browsers will automatically buffer the first 256 bytes.
            Response.Write("<!--");
            Response.Write(new string('*', 256));
            Response.Write("-->");
            Response.Flush();
        }
    
        public virtual void WritePageAfterStreamingText()
        {
            Response.Write("</pre></body></html>");
        }
    
        public override void Write(string value)
        {
            string encoded = Encode(value);
            Response.Write(encoded);            
            if (FlushAfterEveryWrite)
                Response.Flush();
        }
    
        public override void WriteLine(string value)
        {
            Response.Write(Encode(value) + "\n");
            if (AutoScrollToBottom)
                ScrollToBottom();
            if (FlushAfterEveryWrite)
                Response.Flush();
        }
    
        public override void WriteLine()
        {
            Response.Write('\n');
            if (AutoScrollToBottom)
                ScrollToBottom();
            if (FlushAfterEveryWrite)
                Response.Flush();
        }
    
        private string Encode(string s)
        {
            return s.Replace("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;");
        }
    
        public override void Flush()
        {
            Response.Flush();
        }
    
        public void ScrollToBottom()
        {
            Response.Write("<script>window.scrollTo(0, document.body.scrollHeight);</script>");
        }
    
        public override System.Text.Encoding Encoding
        {
            get { throw new NotImplementedException(); }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多