.NETの依存性注入の基本とAutofacの導入

インターフェース指向プログラミングの実践について考察します。


// NuGetからMicrosoft.Extensions.DependencyInjectionを追加

1. 動物インターフェースの定義


interface IAnimal
{
    void Cry();
}

public class Dog : IAnimal
{
    public void Cry()
    {
        Console.WriteLine("汪汪...");
        Console.WriteLine($"Dog:{this.GetHashCode()}");
    }
}

void TestDependencyInjection()
{
    // 依存関係のインターフェース
    // 1. DIコンテナを作成
    ServiceCollection services = new ServiceCollection();
    // 2. 依存関係を登録
    services.AddSingleton<IAnimal, Dog>();
    // 3. サービスプロバイダーを取得
    ServiceProvider serviceProvider = services.BuildServiceProvider();
    // 4. オブジェクトを取得
    IAnimal animal = serviceProvider.GetRequiredService<IAnimal>();
    animal.Cry();
}

// 実行
TestDependencyInjection();

// 結果
// 汪汪...
// Dog:21083178

2. 依存性注入のライフサイクル

AddSingleton: 単一インスタンス


// 1. DIコンテナを作成
ServiceCollection services = new ServiceCollection();
// 2. 依存関係を登録
services.AddSingleton<IAnimal, Dog>();
// 3. サービスプロバイダーを取得
ServiceProvider serviceProvider = services.BuildServiceProvider();
// 4. オブジェクトを取得
IAnimal animal = serviceProvider.GetRequiredService<IAnimal>();
animal.Cry();
IAnimal animal1 = serviceProvider.GetRequiredService<IAnimal>();
animal1.Cry();

// 結果
// 汪汪...
// Dog:21083178
// 汪汪...
// Dog:21083178

AddTransient: トランザイエント(多インスタンス)


// 1. DIコンテナを作成
ServiceCollection services = new ServiceCollection();
// 2. 依存関係を登録
services.AddTransient<IAnimal, Dog>();
// 3. サービスプロバイダーを取得
ServiceProvider serviceProvider = services.BuildServiceProvider();
// 4. オブジェクトを取得
IAnimal animal = serviceProvider.GetRequiredService<IAnimal>();
animal.Cry();
IAnimal animal1 = serviceProvider.GetRequiredService<IAnimal>();
animal1.Cry();

// 結果
// 汪汪...
// Dog:21083178
// 汪汪...
// Dog:55530882

AddScoped: スコープ


// 1. DIコンテナを作成
ServiceCollection services = new ServiceCollection();
// 2. 依存関係を登録
services.AddScoped<IAnimal, Dog>();
// 3. サービスプロバイダーを取得
ServiceProvider serviceProvider = services.BuildServiceProvider();
// 4. スコープを作成
using (var scope = serviceProvider.CreateScope())
{
    IAnimal animal = scope.ServiceProvider.GetRequiredService<IAnimal>();
    animal.Cry();
}
using (var scope = serviceProvider.CreateScope())
{
    IAnimal animal = scope.ServiceProvider.GetRequiredService<IAnimal>();
    animal.Cry();
}

// 結果
// 汪汪...
// Dog:21083178
// 汪汪...
// Dog:55530882

.NETのMicrosoft.Extensions.DependencyInjectionには以下のような課題があります:

  • バッチインジェクションができない
  • コンストラクタインジェクションのみサポート
  • フィルタリング機能がない

これらの問題を解決するためにAutofacを使用します。NuGetからAutofac.Extensions.DependencyInjectionを追加してください。

Autofacの使用例


public class Cat : IAnimal
{
    // プロパティインジェクション
    public Cat cat { get; set; }
    public void Cry()
    {
        Console.WriteLine($"Cat 喵...");
        Console.WriteLine($"Cat :{this.GetHashCode()}");
    }
}

void TestAutoFacDependencyInjection()
{
    // 1. Autofacコンテナを作成
    ContainerBuilder builder = new ContainerBuilder();
    // 2. 登録
    builder.RegisterType<Cat>().As<IAnimal>().PropertiesAutowired();
    // 3. コンテナサービスをビルド
    IContainer container = builder.Build();
    // 4. オブジェクトを取得
    IAnimal cat = container.Resolve<IAnimal>();
    cat.Cry();
}

// 実行結果
// Cat 喵...
// Cat :55909147

Autofacによるバッチインジェクション


void TestAutoFacBatchDependencyInjection()
{
    // 1. Autofacコンテナを作成
    ContainerBuilder builder = new ContainerBuilder();
    // 2. アセンブリ内のすべてのインターフェースを登録
    builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
           .AsImplementedInterfaces()
           .PropertiesAutowired();
    // 3. コンテナサービスをビルド
    IContainer container = builder.Build();
    // 4. 登録されたすべてのオブジェクトを取得
    var animals = container.Resolve<IEnumerable<IAnimal>>();
    foreach (var item in animals)
    {
        item.Cry();
    }
}

// 実行結果
// Cat 喵...
// Cat :56680499
// 汪汪...
// Dog:40362448
// Sheep 咩...
// Sheep:27717712

タグ: .NET DI 依存性注入 Autofac C#

6月6日 00:44 投稿