

.NET Framework4.0にて開発を行っております。  
クラス内にロギング用の記述がいたるところに散らばってしまい、  
また、クラス内にログ出力記述が入る事によって、クラスが汎用的に使用できなくなり、  
可読性も下がってしまっているので、そこを解決したいと思い、質問させて頂きます。

現状は以下の通りです。

[code]

    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
    
[/code]

ロギング出力用のクラスを用意してあり、そのクラスのメソッドを、ログ出力のタイミングで  
引数を渡して呼び出しているのですが、複数のクラスに記述がまたがってしまったりと、  
とにかく煩雑になってしまいます。  
また、問題解決の目的がロギングのみではなく、処理進行を表すフォームウィンドを操作する際にも同じ仕組が必要となってきています。

<http://www.itmedia.co.jp/im/articles/0410/20/news086.html>  
このサイトを参考にAOPやDIに関して色々と調べてみたのですが、具体的な解決策にたどり着けませんでした。

何か具体的な解決策をご存知でしたら、お願いいたします。


CC BY-SA 3.0
2015-09-09T01:47:26.290
16410
2015-09-10T15:51:49.240
2015-09-09T07:26:13.547
5008
12258
question
visual-studio vb.net delegate
クラス内に存在するロギング用の記述について


.NETであれば、[PostSharp](https://www.postsharp.net/)はいかがでしょうか。  
商用目的でも無料（[このページ](https://www.postsharp.net/purchase/faq)の「Can I use PostSharp
Express for commercial products?」）で使えます。  
無料版は機能制限がありますが、ログ出力であれば十分だと思います。

C#の例で申し訳ないですが、こんな感じで使います：

[code]

    [MyLogging]
    public class ClassX
    {
        public int MethodA(...)
        {
            ...
        }
    }
    
[/code]

`MyLogging`属性はPostSharpのライブラリにあるクラスを継承して自分で作ります。

[code]

    public sealed class MyLoggingAttribute : OnMethodBoundaryAspect
    {
         public override void OnEntry(MethodExecutionArgs args)
         {
             // 対象のメソッドの処理の前に呼ばれる
             // args に引数とか対象クラスのインスタンスとか入ってる
         }
         public override void OnExit(MethodExecutionArgs args)
         {
             // 対象のメソッドの処理の後（returnの後）に呼ばれる
             // args はOnEntryのものと同じだが、戻り値も入ってる
         }
    }
    
[/code]

この属性をクラスに付けると、そのクラスのメソッドが呼ばれるたびに、`OnEntry`と`OnExit`が呼ばれるので、そこでログ出力処理とか書けばOKです。  
クラスではなくメソッドに属性をつければ、そのメソッドだけログ出力できます。

ただ、「XX件のデータを処理」のような出力をするには何らかの工夫が必要だと思います。  
必ず件数を戻り値で返すようにするとか・・・

PostSharpは、Visual Studioの「拡張機能と更新プログラム」で、「オンライン」から検索してインストールすればすぐ使えます。

補足ですが、AOPフレームワークには色々な実現方法があり、PostSharpは「ビルド時にILを書き換える」という方式を採っています。  
なので、量次第ですが、ビルドは遅くなります。  
しかし、「プロキシクラスを使う」方式に比べて、「あるクラスを継承しなければならない」とかの制限が無いですし、実行時のパフォーマンスも有利です。


CC BY-SA 3.0
2015-09-10T11:24:35.857
16475
2015-09-10T15:51:49.240
2015-09-10T15:51:49.240
2238
8078
16410
answer


設計例の参考になるのと、もしくは独自実装からの置き換えも検討できると思い、[NLog](http://nlog-project.org/)を紹介します。

[code]

    using NLog;
    
    public class MyClass
    {
      private static Logger logger = LogManager.GetCurrentClassLogger();
    
      public void MyMethod1()
      {
        logger.Trace("Sample trace message");
        logger.Debug("Sample debug message");
        logger.Info("Sample informational message");
        logger.Warn("Sample warning message");
        logger.Error("Sample error message");
        logger.Fatal("Sample fatal error message");
    
        // alternatively you can call the Log() method 
        // and pass log level as the parameter.
        logger.Log(LogLevel.Info, "Sample informational message");
      }
    }
    
[/code]

クラスの静的メンバーに Logger
を生成して各クラスで利用します。その他の例は[Wiki](https://github.com/nlog/nlog/wiki/Tutorial)に良くまとまっているのでご一読ください。  
コードに記述するログ出力処理は、ログのメッセージとレベル(`Fatal,Error,・・・`)だけで、その出力先(`Target`)やフォーマットは[NLog.Config](https://github.com/nlog/nlog/wiki/Configuration-
file)でコントロールします。デザインが明快で気に入っています。


CC BY-SA 3.0
2015-09-10T13:17:16.027
16476
2015-09-10T13:17:16.027
2238
16410
answer