我有两个课程,我不能以任何方式改变:
第1类:将TextWriter
作为构造函数参数并将其用作输出流。
第2课:提供方法WriteLine(string)
。
我需要一个适配器,这样Class1的所有输出都写入Class2。因此,我启动了一个扩展TextWriter
的适配器并缓冲传入的文本,并在新行到达时将其刷新到class2实例。
但是,TextWriter中有很多方法 - 我应该实现哪些方法? Class1中的输出仅为字符串。
根据MSDN,应该至少覆盖Write(char),但是,这强制我自己完成所有\ r \ n新行处理......
Q1:你知道更好的方法来实现我的目标吗? Q2:如果不是,我应该覆盖哪些TextWriter方法以实现最小的实现工作。
答案 0 :(得分:17)
您需要在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
中的所有TextWriter
方法都会解析为循环中调用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!
答案 1 :(得分:0)
我正在添加另一个答案,因为我无法得到上述答案!
根据我的经验,我必须覆盖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("&", "&").Replace("<", "<").Replace(">", ">");
}
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(); }
}
}