C#
 Computer >> コンピューター >  >> プログラミング >> C#

C#の依存性注入(DI)とは?基本概念と実装例をわかりやすく解説

「依存関係」とは、あるオブジェクトが別のオブジェクトに依存している状態を指します。依存性注入(Dependency Injection、DI)とは、オブジェクトが必要とするインスタンスを、そのオブジェクト自身に生成させるのではなく、外部から提供する設計手法のことです。この手法を活用すると、依存オブジェクトをモック(テスト用の代替オブジェクト)に差し替えられるため、単体テストが格段に行いやすくなります。

例えば、クラスAがクラスBのメソッドを呼び出し、さらにそのクラスBがクラスCのメソッドを呼び出している場合、「AはBに依存し、BはCに依存している」ことになります。依存性注入を使えば、各クラスの内部でBやCのインスタンスを生成する代わりに、クラスCのインスタンスをクラスBへ、クラスBのインスタンスをクラスAへと、外部から渡すことができます。

問題のあるコード例

以下の例では、RunnerクラスがLoggerクラスに依存しています。注目していただきたいのは、Runnerクラスのコンストラクタ内でLoggerのインスタンスを直接生成しているという点です。このコードには、次のような問題があります。

  • LoggerクラスがRunnerと密結合しており、Runnerのコードを修正しない限り、他のクラスに差し替えることができない。
  • Logger自体に依存関係がある場合、Runner側でLoggerをインスタンス化する前に、それらの依存関係を設定しなければならない。
  • テストが難しくなる。Loggerがネットワークアクセスやファイルシステムへのアクセスなど、リソースを大量に消費するクラスである場合、テストの実行速度が低下するうえ、簡単には置き換えられない。
using System;
class Program{
    static void Main(string[] args){
        var runner = new Runner();
        runner.Run();
    }
}
class Runner{
    private Logger _logger;
    public Runner(){
        _logger = new Logger();
    }
    public void Run(){
        // 何らかの処理を行う
        _logger.Log("Message to be logged");
    }
}
class Logger{
    public void Log(string message){
        Console.WriteLine(message);
    }
}

依存性注入による改善

依存性注入を適用するには、Runnerのコンストラクタを修正し、具象クラスではなくILoggerインターフェースを受け取るように変更します。あわせて、LoggerクラスにはILoggerインターフェースを実装させます。これにより、LoggerクラスのインスタンスをRunnerのコンストラクタに渡せるようになります。

このアプローチの大きな利点は、テスト時に発揮されます。ILoggerを実装したTestLoggerクラスを作成し、それをRunnerのコンストラクタに渡すだけで、実際のLoggerに影響を与えることなくテストを行えます。

コード例

using System;
class Program{
    static void Main(string[] args){
        var logger = new Logger();
        var runner = new Runner(logger);
        runner.Run();
    }
}
class Runner{
    private ILogger _logger;
    public Runner(ILogger logger){
        _logger = logger;
    }
    public void Run(){
        // 何らかの処理を行う
        _logger.Log("Message to be logged");
    }
}
interface ILogger{
    void Log(string message);
}
class Logger : ILogger{
    public void Log(string message){
        Console.WriteLine(message);
    }
}

実行結果

Message to be logged
  1. C#のクラスとは?基本概念からコンストラクタまで徹底解説

    C#におけるクラスは、最も重要な型の一つです。クラスは、問題領域に関連するオブジェクトを生成するための「設計図」と考えることができます。つまり、クラスはテンプレートであり、そこからオブジェクトを作成します。クラスには、そのクラスから作られるオブジェクト群が共有する構造(データ)と振る舞い(メソッド)が定義されています。たとえるなら、クラスは「クッキーの型」であり、オブジェクトはその型で作られた「クッキー」そのものです。 カプセル化という重要な概念 クラスは、オブジェクト指向プログラミングにおける重要な概念である「カプセル化」を実現します。カプセル化とは、データと、そのデータを操作する処理を一箇

  2. C#のConsoleクラスとは?主要プロパティの使い方を実例付きで解説

    C#のConsoleクラスは、コンソールアプリケーションにおける標準入力・標準出力・標準エラー出力の各ストリームを表すクラスです。テキストの表示や入力の読み取りだけでなく、文字色や背景色の変更、カーソル位置やサイズの制御など、コンソール操作に関するさまざまな機能が提供されています。ここでは、Consoleクラスの代表的なプロパティの使い方を、サンプルコードと実行結果とあわせて解説します。Console.CursorLeftプロパティコンソール上のカーソル位置(左端から数えた列位置)を変更するには、Console.CursorLeftプロパティを使用します。サンプルコードusing System