Alva

Alva

programmer
github
telegram
email

dotnetの依存性注入-03.依存関係とコンストラクタの検出ルール

本文示例代码,均采用 .NET 6,具体的代码可以在这个仓库 Articles.DI 中获取。

前面的文章中,我们提及了依赖注入的基本使用。我们使用了简单的案例,注册了IMessageWriter接口,以及编写了两个实现类MessageWriterLoggingMessageWriter,但是它们二者都只有一个构造函数。如果我们注册服务时,实现类有多个构造函数时,容器该如何选择呢?

如何选择构造函数#

我们可以直接写代码,来模拟这个场景。有一个服务 ExampleService,它有多个构造函数,这些构造函数所需参数的数量有多有少,同时需要的类型也各有不同,具体看下面的代码:

// https://github.com/alva-lin/Articles.DI/tree/master/WorkerService3
public class ExampleService
{
    public ExampleService() => Console.WriteLine("空のコンストラクタ");

    public ExampleService(AService aService) =>
        Console.WriteLine("単一引数のコンストラクタ:AService");

    public ExampleService(AService aService, BService bService) =>
        Console.WriteLine("二つの引数のコンストラクタ:AService, BService");

    public ExampleService(AService aService, CService cService) =>
        Console.WriteLine("二つの引数のコンストラクタ:AService, CService");
}

public class AService
{
    public AService() => Console.WriteLine("AServiceのインスタンス化");
}

public class BService
{
    public BService() => Console.WriteLine("BServiceのインスタンス化");
}

public class CService
{
    public CService() => Console.WriteLine("CServiceのインスタンス化");
}

ExampleServiceクラスには 4 つのコンストラクタがあり、3 つのサービスに依存しています。サービスを登録する際には、AServiceBServiceのみを登録します。

IHost host = Host.CreateDefaultBuilder(args)
   .ConfigureServices(services =>
    {
        services.AddHostedService<Worker>();
        services.AddSingleton<ExampleService>();

        // 異なる組み合わせを作成するために、以下のコードをコメントアウト(またはコメント解除)して実行結果を確認してください
        services.AddSingleton<AService>();
        services.AddSingleton<BService>();
        // services.AddSingleton<CService>();
    })
   .Build();

await host.RunAsync();

public class Worker : BackgroundService
{
    private readonly ExampleService _exampleService;

    // ExampleServiceのインスタンスが注入されていますが、どのコンストラクタが呼び出されているのでしょうか?
    public Worker(ExampleService exampleService)
    {
        _exampleService = exampleService;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        // 何も実行しない
    }
}

上記のコードの実行結果は次の通りです。

AServiceのインスタンス化
BServiceのインスタンス化
二つの引数のコンストラクタ:AService, BService

結果からわかるように、コンテナはExampleServiceクラスをインスタンス化する際に、3 番目のコンストラクタを使用しています。すべてのコンストラクタを比較すると、3 番目と 4 番目のコンストラクタが最も多くのパラメータを必要としていますが、4 番目のコンストラクタはCServiceクラスを必要としていますが、このサービスはコンテナに登録されていないため、コンテナは 4 番目のコンストラクタを選

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。