プログラムを中心とした個人的なメモ用のブログです。 タイトルは迷走中。
内容の保証はできませんのであしからずご了承ください。

2019/02/19

.NET Core でジェネリック型の DI を行う

event_note2019/02/19 4:28

.NET Core の DI サービスにおいて、ジェネリック型の DI を行う方法について調べてみました。

とりあえず以下のサイトでわかりやすく説明されています。

ASP.NET Core と書かれていますが、DI の機能は Microsoft.Extensions.DependencyInjection で提供されているので、別に .NET Core のコンソールアプリなどでも使えます。

環境

  • .NET Core 2.1
  • Visual Studio 2017

サンプルコード

以下のようなインターフェイスがあるとします。

public interface IThing<T>
{
    string GetName { get; }
}

このインターフェイスの実装を以下のようにしたとします。

public class GenericThing<T> : IThing<T>
{
    public GenericThing()
    {
        GetName = typeof(T).Name;
    }

    public string GetName { get; }
}

これを DI サービスに登録する場合、以下のように書きます。

serviceCollection.AddSingleton(typeof(IThing<>), typeof(GenericThing<>));

注入されるクラスでは以下のように書きます。

public class Class1
{
    private readonly IThing<Class1> _thing;

    public Class1(IThing<Class1> thing)
    {
        _thing = thing;
        Console.WriteLine(_thing.GetName);
    }
}

以下メインメソッドのサンプルです。

static void Main(string[] args)
{
    IServiceCollection services = new ServiceCollection();

    // DI サービスへの登録
    services.AddSingleton(typeof(IThing<>), typeof(GenericThing<>));
    services.AddSingleton<Class1>();

    // DI サービスのビルド
    IServiceProvider serviceProvider = services.BuildServiceProvider();

    var service = serviceProvider.GetService<Class1>();

    Console.ReadKey();
}

出力結果

Class1

もう少し汎用的に

インターフェイスを以下のように定義しておけば、

public interface IThing<T> : IThing
{
}

public interface IThing
{
    string GetName { get; }
}

注入されたオブジェクトを非ジェネリック型の変数に格納できます。

public class Class1
{
    private readonly IThing _thing;

    public Class1(IThing<Class1> thing)
    {
        _thing = thing;
        Console.WriteLine(_thing.GetName);
    }
}