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()); } }
执行结果
当然在项目中,我们绝对不能编写这样的硬代码,我们希望通过配置文件选择特定的实现