.NET Core中具有多个实现的依赖注入实现

0x01 前言

.NET Core Microsoft依赖注入(DI)非常有用,但是如何处理具有多种实现的接口? 运行时可以基于配置选择这些实现之一吗? 可以反射实现吗?

0x02 一个接口实现2个类

接口定义:

public interface IHelloer
{
    string SayHello();
}

具体实现:

public class HelloerA : IHelloer
{
    public string SayHello()
    {
        return $"Hello from {nameof(HelloerA)}";
    }
}

public class HelloerB : IHelloer
{
    public string SayHello()
    {
        return $"Hello from {nameof(HelloerB)}";
    }
}

依赖注入:

将HelloerA和HelloerB都注册到DI容器中。

 services.AddTransient<IHelloer, HelloerA>();
 services.AddTransient<IHelloer, HelloerB>();

 

刚才我们注册了同一接口的两组实现,那么.Net Core运行时将选择哪种实现?

完整代码:

class Program
    {
        static void Main(string[] args)
        {
            IServiceCollection services = new ServiceCollection();
            services.AddTransient<IHelloer, HelloerA>();
            services.AddTransient<IHelloer, HelloerB>();
            var builder = services.BuildServiceProvider();

            var message = builder.GetRequiredService<IHelloer>();
            Console.WriteLine(message.SayHello());
        }
    }

Ctrl+F5 执行后,控制台上会输出:

Hello from HelloerB

 

 如上图:结果是HelloerB,这是我们在DI容器中注册的最后一项。 问题来了,如果我想在运行时使用HelloerA,该怎么办?

 

实际上,在.NET Core中,当您为一个接口注册多个实现时,可以向构造函数注入该接口的集合,即所有已注册的实现。

 class Program
    {
        static void Main(string[] args)
        {
            IServiceCollection services = new ServiceCollection();
            services.AddTransient<IHelloer, HelloerA>();
            services.AddTransient<IHelloer, HelloerB>();
            var builder = services.BuildServiceProvider();

            var message = builder.GetRequiredService<IEnumerable<IHelloer>>();
            Console.WriteLine(message.First().SayHello());
        }
    }

 

执行结果

 

当然在项目中,我们绝对不能编写这样的硬代码,我们希望通过配置文件选择特定的实现

 

posted @ 2021-01-14 14:23  cnkker.com  阅读(400)  评论(0编辑  收藏  举报