アスペクトほしいよー、とかなんとか。
ことの発端。
TextWriter writer=new SomeTextWriter("hogehoge"); tw.Write( Something() ); tw.Write( AnotherSomething() );
なんてコードがあって。
デバッグのために、Writeされた内容を表示したくなったとしよう(というか、したんですよ)。
string content= Something();
tw.Write(content);
Console.Write(content);
content= AnotherSomething();
tw.Write(content);
なんてやりかたは大変残念、対象のTextWriterが書いた内容を覚えていれば
TextWriter writer=new LoggedWriter(new SomeTextWriter("hogehoge")); tw.Write( Something() ); tw.Write( AnotherSomething() ); Console.WriteLine(tw.GetWroteString());
で済む話なんですよ。というわけでDecoratorパターン。
class LoggedTextWriter:TextWriter { public LoggedTextWriter(TextWriter writer) { _writer=writer; } TextWriter _writer; //ここでTextWriterのvirtualメソッドをすべてoverride、_writerに移譲してやればよい }
はい簡単ですね…… って全然簡単じゃないよ!「すべて」っていったいいくつあると思っているんだ。幸いなことにVisualStudioだとoverrideって書いた時点で補完がきくのだけど、でも最終的には
public class LoggedTextWriter:TextWriter { public LoggedTextWriter(TextWriter writer) { _writer = writer; } TextWriter _writer; public override void Write(bool value) { _writer.Write(value); } public override void Write(char value) { _writer.Write(value); } public override void Write(char[] buffer, int index, int count) { _writer.Write(buffer, index, count); } public override void Close() { _writer.Close(); } public override void Flush() { _writer.Flush(); } public override void WriteLine(object value) { _writer.WriteLine(value); } public override string NewLine { get { return _writer.NewLine; } set { _writer.NewLine = value; } } // 以下略。 }
という大変残念なコードを書く必要があって、さらにこのいっこいっこにロギング処理を書いたり書かなかったり……。
そんなときのためのアスペクトなんですな、ということを実感した次第。
しかしこの程度のためにわざわざAOPフレームワーク導入とかあほすぎるので、もうちょいシンプルでクリーンでライトウエイトなソリューションが欲しいものです(特にオチはない)。
rubyだと特異メソッドでがちゃがちゃってできるんですけどねえ。