質問: .NET Framework4.0にて開発を行っております。 クラス内にロギング用の記述がいたるところに散らばってしまい、 また、クラス内にログ出力記述が入る事によって、クラスが汎用的に使用できなくなり、 可読性も下がってしまっているので、そこを解決したいと思い、質問させて頂きます。 現状は以下の通りです。 ``` private class x private sub exec() --処理開始のログ出力記述 --処理1 ----クラスX.メソッドA ----クラスX.メソッドAでXX件のデータを処理 ----クラスX.メソッドAが正常終了しました --処理2 ----クラスY.メソッドA ----クラスY.メソッドAでXX件のデータを処理 ----クラスY.メソッドAが正常終了しました --処理終了のログ出力記述 End sub end class ``` ロギング出力用のクラスを用意してあり、そのクラスのメソッドを、ログ出力のタイミングで 引数を渡して呼び出しているのですが、複数のクラスに記述がまたがってしまったりと、 とにかく煩雑になってしまいます。 また、問題解決の目的がロギングのみではなく、処理進行を表すフォームウィンドを操作する際にも同じ仕組が必要となってきています。 このサイトを参考にAOPやDIに関して色々と調べてみたのですが、具体的な解決策にたどり着けませんでした。 何か具体的な解決策をご存知でしたら、お願いいたします。
回答: .NETであれば、PostSharpはいかがでしょうか。 商用目的でも無料(このページの「Can I use PostSharp Express for commercial products?」)で使えます。 無料版は機能制限がありますが、ログ出力であれば十分だと思います。 C#の例で申し訳ないですが、こんな感じで使います: ``` [MyLogging] public class ClassX { public int MethodA(...) { ... } } ``` `MyLogging`属性はPostSharpのライブラリにあるクラスを継承して自分で作ります。 ``` public sealed class MyLoggingAttribute : OnMethodBoundaryAspect { public override void OnEntry(MethodExecutionArgs args) { // 対象のメソッドの処理の前に呼ばれる // args に引数とか対象クラスのインスタンスとか入ってる } public override void OnExit(MethodExecutionArgs args) { // 対象のメソッドの処理の後(returnの後)に呼ばれる // args はOnEntryのものと同じだが、戻り値も入ってる } } ``` この属性をクラスに付けると、そのクラスのメソッドが呼ばれるたびに、`OnEntry`と`OnExit`が呼ばれるので、そこでログ出力処理とか書けばOKです。 クラスではなくメソッドに属性をつければ、そのメソッドだけログ出力できます。 ただ、「XX件のデータを処理」のような出力をするには何らかの工夫が必要だと思います。 必ず件数を戻り値で返すようにするとか・・・ PostSharpは、Visual Studioの「拡張機能と更新プログラム」で、「オンライン」から検索してインストールすればすぐ使えます。 補足ですが、AOPフレームワークには色々な実現方法があり、PostSharpは「ビルド時にILを書き換える」という方式を採っています。 なので、量次第ですが、ビルドは遅くなります。 しかし、「プロキシクラスを使う」方式に比べて、「あるクラスを継承しなければならない」とかの制限が無いですし、実行時のパフォーマンスも有利です。