21

我有两门课,我不能以任何方式改变它们:

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

第 2 类:提供方法WriteLine(string)

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

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

根据 MSDN,至少应该覆盖 Write(char) ,但是,这迫使我也必须自己处理所有 \r\n 新行...

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

4

2 回答 2

26

您需要做的就是Write(char)在派生类上实现。TextWriter如果有人调用WriteLine您的新类,WriteLine则会调用基类方法。Write它会做正确的事:用个人\r\n角色调用你的方法。

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

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

并且Write(string)实际上是:

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

解析为循环调用的所有Write方法。TextWriterWrite(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!
于 2013-07-18T00:46:26.140 回答
2

我正在添加另一个答案,因为我无法获得上述答案!

根据我的经验,我必须重写WriteLine()andWriteLine(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(); }
    }
}
于 2013-10-23T16:30:30.697 回答