bugfix> c# > 投稿

プログラム全体でログをテキストファイルに書き込むクラスがあります。メソッドを static にするのは良い考えだと思いました少数のメソッドしかなく、プログラムのさまざまな部分で呼び出されるためです。このメソッドは、初期ファイルを作成するためにプログラムの開始時に一度呼び出されます。

public static void CreateAuditLog()
{
    var fileName = Path.Combine(filePath, 
        $@"AuditFile{DateTime.Now:yyyy-MM-dd_hh-mm-ss-fff}.txt");
    writer = new StreamWriter(new FileStream(fileName,
        FileMode.CreateNew, FileAccess.Write));
    GetAuditLogFileSize();
}

しかし、単体テストを書くとき、静的メソッドを呼び出すメソッドをテストできないことを知りませんでした。 (コードベースのメソッド例)

public Decimal CalculateCurrentBalance
{
    get
    {
        var balance = TotalAmountBilled - TotalAmountPaid;
        Audit.Message(2, $"Balance: {balance} for: {Name}");
        return TotalAmountBilled - TotalAmountPaid;
    }
}

メッセージメソッドには多くの詳細があるため、ここではすべてを投稿しませんが、基本的にはテキストファイルにログを記録するために番号とメッセージを受け取ります。ストリームライターは、意図的に CreateAuditLog() で開いたままになります。そのため、 Message() さまざまな場所で呼び出すことができ、メッセージはログファイルに書き込まれます。

public static void Message(int auditLevel, string message)

このプログラムの設計方法が悪いように感じます。誰が私がこれを再設計することができるかについての提案を持っていますか?プログラム内の他のすべてのクラスでロギングクラスのインスタンスを作成せずにこれをどのように行うことができるかわかりません。

回答 1 件
  • しないでください作成する 他のすべてのクラスのインスタンス。注入する 1。

    これは、単体テストの基本の1つです。依存性注入。クラスは依存関係を作成したり、直接依存関係にアクセスしたりすることはなく、使用するものが渡されます。この場合、 Log   ILogger を実装したクラス  (作成するインターフェイス)クラスは次のようになります。

    public class MyInjectedClass
    {
         private readonly ILogger logger;
         public MyInjectedClass(ILogger logger)
         {
            this.logger = logger;
         }
         public void SomeMethod()
         {
            logger.Message();
         }
    }
    
    

    もちろん、今は ILogger のインスタンスを渡す必要があります  いたるところにあり、それは大きな面倒です。幸い、 NInject のようなライブラリがたくさんあります  および Autofac  それはあなたのためにすべての依存関係を結び付けます。リファクタリングが必要になりますが、完了したらロギングクラスを ILogger のシングルトンとして登録するだけです  インターフェースと依存関係としてそれを持っているすべてのクラスに自動的に注入されます。

    (MSには、.NET Coreを使用している場合、DIライブラリも含まれています)

    インターフェイスは次のようになります。

    public interface ILogger
    {
         void Message(string msg);
    }
    
    

あなたの答え