インターフェース指向プログラミングの実践について考察します。
// 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