【C#】コンソールアプリでDIを使う

.NET 6 でコンソールアプリに DI (=Dependency Injection) 環境を作成して、オブジェクトに依存関係を注入するところまでを確認したいと思います。

使用するライブラリは、「Microsoft.Extensions.DependencyInjection」です。

確認環境

動作確認環境は以下の通りです。

  • VisualStudio2022
  • .NET6 + C#10.0
  • Microsoft.Extensions.DependencyInjection 6.0.0

環境作成

パッケージマネージャーコンソールで以下コマンドを打ちます。

// メニュー
ツール > NuGet パッケージ マネージャー > パッケージ マネージャー コンソール

// コマンド
// https://www.nuget.org/packages/Microsoft.Extensions.DependencyInjection
> Install-Package Microsoft.Extensions.DependencyInjection -Version 6.0.0

そうすると以下のように「ServiceCollection」クラスが使用可能になるのでこれで DI 環境がもう作れています。

動作確認

以下サンプルの登場人物は以下の通りです。

名前 説明
ISample インジェクションするインターフェース
Sample インジェクションする実装クラス
Service 依存関係を注入されるサービスクラス

シングルトンとして登録したISampleをコンストラクタインジェクションするサンプルです。

using System;
using Microsoft.Extensions.DependencyInjection; // 追加で宣言する

namespace ConsoleApp1
{
    internal class AppMain
    {
        static readonly IServiceCollection _services = new ServiceCollection();
        static ServiceProvider _provider;

        private static void Main(string[] args)
        {
            // インジェクションするほう
            _services.AddSingleton<ISample, Sample>();
            // インジェクションされるほう
            _services.AddSingleton<Service>();
            
            // 解決してくれるやつ
            _provider = _services.BuildServiceProvider();

            // DI済みのインスタンスを取得(1)
            var service1 = _provider.GetRequiredService<Service>();
            service1.Update();
            service1.Dump();
            // > ID=4d418ae4-def4-44e8-8a3e-a12898d99c40

            // DI済みのインスタンスを取得(2)
            var service2 = _provider.GetService<Service>();
            service2.Dump();
            // > ID=4d418ae4-def4-44e8-8a3e-a12898d99c40
            service2.Update();
            service2.Dump();
            // > ID=3ae70caf-3bf8-4440-b9a2-d67ca7fafd01
        }
    }

    public interface ISample
    {
        string ID { get; set; }
    }

    public class Sample : ISample
    {
        public string ID { get; set; }
    }

    public class Service
    {
        ISample _sample;

        public Service(ISample sample) // コンストラクタインジェクションで解決される
        {
            _sample = sample;
        }

        public void Update()
        {
            _sample.ID = Guid.NewGuid().ToString(); // サンプルで一意のIDを発行する
        }

        public void Dump()
        {
            Console.WriteLine($"ID={_sample.ID}"); // オブジェクトの内容をコンソールに出す
        }
    }
}

コンソールだと「Scoped」がどういう単位か判然としないので、「AddTransient」か「AddSingleton」を使用することになると思います。