DIでServiceCollectionに同じInterfaceのクラスを複数登録する

もくじ
https://tera1707.com/entry/2022/02/06/144447

やりたいこと

以前の記事で、IocServiceCollection を使って、DI(Dependency Injection)をやったが、そのときコンストラクタで受けるクラスは、それぞれ別のインターフェースを実装するクラスだった。

同じインターフェースを実装したクラスを複数受け取りたいときはどうしたらいいか?調べてみる。

まずこまったこと

下記のツールを作ってるときにおきたこと。

https://github.com/tera1707/FileVerUpTool

下記のコンストラクタのように、同じインターフェースを実装したクラスを3つ受け取りたかった。

public VersionReadWrite(ISearchSpecifiedExtFile ssef, IProjMetaDataHandler mdh1, IProjMetaDataHandler mdh2, IProjMetaDataHandler mdh3)
{
    _finder = ssef;
    _sdkcsproj = mdh1;
    _dfwcsproj = mdh2;
    _cppproj = mdh3;
}

そのために、services.AddSingletonを、下記のように3回読んで、3つ分登録しようとした。

services.AddSingleton<IProjMetaDataHandler, SdkTypeCsprojHandler>();
services.AddSingleton<IProjMetaDataHandler, DotnetFrameworkProjHandler>();
services.AddSingleton<IProjMetaDataHandler, CppProjHandler>();

そうすると、コンストラクタで受け取るIProjMetaDataHandlerを実装したクラスが、3つとも、3個目に登録したCppProjHandlerになってしまった。
おそらく、前の二つは、最後のCppProjHandlerに後勝ちで上書きされたものと思われる。

なので、今回は下記のようにした。

登録する個所

services.AddSingleton<IProjMetaDataHandler[]>(x => new IProjMetaDataHandler[] { new SdkTypeCsprojHandler(), new DotnetFrameworkProjHandler(), new CppProjHandler() });

使うコンストラク

public VersionReadWrite(ISearchSpecifiedExtFile ssef, IProjMetaDataHandler[] handlers)
{
    _finder = ssef;
    _sdkcsproj = handlers[0];
    _dfwcsproj = handlers[1];
    _cppproj = handlers[2];
}

これで、うまく、同じインターフェースを実装したクラスを3つ分受け取ることができた。