情報アイランド

「情報を制する者は世界を制す」をモットーに様々な情報を提供することを目指すブログです。現在はプログラミング関連情報が多めですが、投資関連情報も取り扱っていきたいです。

C#で標準出力に出力する前後に処理を行う

ログなどの出力機能を実装する場合、全く独自の仕組みを作ることもできますが、そのようにするとログ機能を呼び出すコードがプログラム全体に散らばり、プログラムの一部を別のプログラムの為に再利用することが難しくなります。できることなら、標準のConsole.WriteメソッドやConsole.WriteLineメソッドを使って出力処理を行い、再利用性の高いコードにするべきかと思います。

そこでConsole.SetOutメソッドを用い、Console.WriteメソッドやConsole.WriteLineメソッドが呼ばれたら独自のTextWriterにデータが流れるようにして、独自のTextWriterの内部で必要に応じた処理を行います。

TextWriterを継承するCustomOutクラスを以下のように実装します。TextWriterWriteメソッドやWriteLineメソッドを全て上書きしています。

CustomOutクラスが実体化された時に、Console.Outに設定されているTextWriterinnerout変数に保持しておきます。WriteメソッドやWriteLineメソッドが呼ばれた時には任意の事前処理を行い、inneroutに保持されたTextWriterへ出力を行い、更に事後処理を行います。また、事前処理と事後処理に対しては出力される文字列と標準出力(stdout)を渡しています。

public delegate void CustomOutProc(string text, TextWriter stdout);

public class CustomOut : TextWriter
{
    public CustomOut()
    {
        if (stdout == null)
            stdout = Console.Out;

        innerout = Console.Out;

        Console.SetOut(this);
    }

    private static TextWriter stdout = null;
    private TextWriter innerout = null;

    public CustomOutProc Beforehand { get; set; }
    public CustomOutProc Afterward { get; set; }

    public override Encoding Encoding
    {
        get { return innerout.Encoding; }
    }

    private void InnerWrite(string text)
    {
        if (Beforehand != null)
            Beforehand(text, stdout);
        innerout.Write(text);
        if (Afterward != null)
            Afterward(text, stdout);
    }

    private void InnerWriteLine(string text)
    {
        if (Beforehand != null)
            Beforehand(text, stdout);
        innerout.WriteLine(text);
        if (Afterward != null)
            Afterward(text, stdout);
    }

    public override void Write(bool value)
    {
        InnerWrite(value.ToString());
    }

    public override void Write(char value)
    {
        InnerWrite(value.ToString());
    }

    public override void Write(char[] buffer)
    {
        InnerWrite(new string(buffer));
    }

    public override void Write(char[] buffer, int index, int count)
    {
        InnerWrite(new string(buffer, index, count));
    }

    public override void Write(decimal value)
    {
        InnerWrite(value.ToString());
    }

    public override void Write(double value)
    {
        InnerWrite(value.ToString());
    }

    public override void Write(float value)
    {
        InnerWrite(value.ToString());
    }

    public override void Write(int value)
    {
        InnerWrite(value.ToString());
    }

    public override void Write(long value)
    {
        InnerWrite(value.ToString());
    }

    public override void Write(object value)
    {
        InnerWrite(value.ToString());
    }

    public override void Write(string format, object arg0)
    {
        InnerWrite(string.Format(format, arg0));
    }

    public override void Write(string format, object arg0, object arg1)
    {
        InnerWrite(string.Format(format, arg0, arg1));
    }

    public override void Write(string format, object arg0, object arg1, object arg2)
    {
        InnerWrite(string.Format(format, arg0, arg1, arg2));
    }

    public override void Write(string format, params object[] arg)
    {
        InnerWrite(string.Format(format, arg));
    }

    public override void Write(string value)
    {
        InnerWrite(value);
    }

    public override void Write(uint value)
    {
        InnerWrite(value.ToString());
    }

    public override void Write(ulong value)
    {
        InnerWrite(value.ToString());
    }

    public override void WriteLine()
    {
        InnerWriteLine("");
    }

    public override void WriteLine(bool value)
    {
        InnerWriteLine(value.ToString());
    }

    public override void WriteLine(char value)
    {
        InnerWriteLine(value.ToString());
    }

    public override void WriteLine(char[] buffer)
    {
        InnerWriteLine(new string(buffer));
    }

    public override void WriteLine(char[] buffer, int index, int count)
    {
        InnerWriteLine(new string(buffer, index, count));
    }

    public override void WriteLine(decimal value)
    {
        InnerWriteLine(value.ToString());
    }

    public override void WriteLine(double value)
    {
        InnerWriteLine(value.ToString());
    }

    public override void WriteLine(float value)
    {
        InnerWriteLine(value.ToString());
    }

    public override void WriteLine(int value)
    {
        InnerWriteLine(value.ToString());
    }

    public override void WriteLine(long value)
    {
        InnerWriteLine(value.ToString());
    }

    public override void WriteLine(object value)
    {
        InnerWriteLine(value.ToString());
    }

    public override void WriteLine(string format, object arg0)
    {
        InnerWriteLine(string.Format(format, arg0));
    }

    public override void WriteLine(string format, object arg0, object arg1)
    {
        InnerWriteLine(string.Format(format, arg0, arg1));
    }

    public override void WriteLine(string format, object arg0, object arg1, object arg2)
    {
        InnerWriteLine(string.Format(format, arg0, arg1, arg2));
    }

    public override void WriteLine(string format, params object[] arg)
    {
        InnerWriteLine(string.Format(format, arg));
    }

    public override void WriteLine(string value)
    {
        InnerWriteLine(value);
    }

    public override void WriteLine(uint value)
    {
        InnerWriteLine(value.ToString());
    }

    public override void WriteLine(ulong value)
    {
        InnerWriteLine(value.ToString());
    }
}

この機能の簡単な使い方を以下に示します。BeforehandAfterwardでは任意の処理を実行できますが、ここでは標準出力にメッセージを表示するようにしています。BeforehandAfterward内でConsole.WriteメソッドやConsole.WriteLineメソッドを使用するとスタックオーバーフローになることに注意してください。

CustomOut customOut = new CustomOut();
customOut.Beforehand = (text, stdout) =>
{
    stdout.WriteLine("標準出力に出力します。");
};
customOut.Afterward = (text, stdout) =>
{
    stdout.WriteLine("標準出力に出力しました。");
};

Console.WriteLine("test");

結果は以下のようになります。

処理を入れ子にする場合は、CustomOutクラスを複数作成します。

CustomOut customOut = new CustomOut();
customOut.Beforehand = (text, stdout) =>
{
    stdout.WriteLine("標準出力に出力します。");
};
customOut.Afterward = (text, stdout) =>
{
    stdout.WriteLine("標準出力に出力しました。");
};

CustomOut customOut2 = new CustomOut();
customOut2.Beforehand = (text, stdout) =>
{
    stdout.WriteLine("----------------------------------------------------------------------");
};
customOut2.Afterward = (text, stdout) =>
{
    stdout.WriteLine("----------------------------------------------------------------------");
};

Console.WriteLine("test");

結果は以下のようになります。

pizyumi
プログラミング歴19年のベテランプログラマー。業務システム全般何でも作れます。現在はWeb系の技術を勉強中。
スポンサーリンク

-C#