.NET Core の DI サービスにおいて、複数のインターフェイスを実装したクラスの DI を行う方法について試してみました。
正直これでいいのかなという感じですが・・・。
尚、DI の機能は ASP.NET Core として解説されているものが多いですが、DI の機能自体は Microsoft.Extensions.DependencyInjection
で提供されているので、ASP.NET Core に限らず .NET Core のコンソールアプリなどでも使えます。
環境
- .NET Core 2.1
- Visual Studio 2017
インターフェイスと実装クラス
以下のような2つのインターフェイスがあったとします。
interface IFoo
{
string GetFoo();
}
interface IBar
{
string GetBar();
}
この2つのインターフェイスを以下のように実装したとします。
class ImplClass : IFoo, IBar
{
public ImplClass()
{
var guid = Guid.NewGuid();
Console.WriteLine($"GUID={guid}");
}
public string GetFoo() => "Foo";
public string GetBar() => "Bar";
}
この ImplClass
を以下のように IFoo
IBar
として DI する場合を考えてみます。
class Class1
{
public Class1(IFoo foo)
{
Console.WriteLine(foo.GetFoo());
}
}
class Class2
{
public Class2(IBar bar)
{
Console.WriteLine(bar.GetBar());
}
}
異なる実体での DI
この場合は簡単です。
以下のように、ImplClass
を IFoo
IBar
としてそれぞれ登録します。
static void Main(string[] args)
{
IServiceCollection services = new ServiceCollection();
services.AddSingleton<IFoo, ImplClass>();
services.AddSingleton<IBar, ImplClass>();
services.AddSingleton<Class1>();
services.AddSingleton<Class2>();
IServiceProvider serviceProvider = services.BuildServiceProvider();
serviceProvider.GetService<Class1>();
serviceProvider.GetService<Class2>();
Console.ReadKey();
}
実行結果
GUID=83b231eb-49db-4e5a-bfea-0e3d0c6f369e
Foo
GUID=175790cf-0382-4482-a9a0-69baf900424c
Bar
GUID を見てわかるように実体は異なります。
実体は1つだけど、異なる型で DI する場合
この場合、少し工夫が必要です。
以下のように、先に ImplClass
を登録した上で、IFoo
と IBar
の登録時には ImplClass
の実体を IServiceProvider
から取得します。
static void Main(string[] args)
{
IServiceCollection services = new ServiceCollection();
services.AddSingleton<ImplClass>();
services.AddSingleton<IFoo>(x => x.GetService<ImplClass>());
services.AddSingleton<IBar>(x => x.GetService<ImplClass>());
services.AddSingleton<Class1>();
services.AddSingleton<Class2>();
IServiceProvider serviceProvider = services.BuildServiceProvider();
serviceProvider.GetService<Class1>();
serviceProvider.GetService<Class2>();
Console.ReadKey();
}
実行結果
GUID=26dd36ef-7cc9-4001-a591-5b229c2edd48
Foo
Bar
ImplClass
のコンストラクタが一回しか呼ばれておらず、実体が1つであることがわかります。