.NET Core依赖注入中如何注册多实现并单独获取指定实现
这问题我之前在项目里也踩过坑!核心原因很简单:你当前的注册方式只把MyInterface和它的实现类做了绑定,但DI容器并没有把实现类本身注册为可直接解析的服务,所以直接调用GetService<FirstImplementation>()时,容器找不到对应的注册项,自然返回null。
给你两个实用的解决方案,按需选择:
方案1:同时注册实现类本身
在注册接口关联的同时,把每个实现类也单独注册到容器里,这样既可以通过接口获取全部实现,也能直接获取具体类的实例:
// 先注册具体实现类本身 services.AddSingleton<FirstImplementation>(); services.AddSingleton<SecondImplementation>(); // 再将接口与已注册的实现类实例关联 services.AddSingleton<MyInterface>(sp => sp.GetRequiredService<FirstImplementation>()); services.AddSingleton<MyInterface>(sp => sp.GetRequiredService<SecondImplementation>());
这样之后,你既可以用serviceProvider.GetServices<MyInterface>()获取所有实现,也能直接用serviceProvider.GetRequiredService<FirstImplementation>()拿到目标实例,不用再遍历筛选。
方案2:使用.NET 6+的Keyed服务(更优雅的区分接口实现)
如果你的项目基于.NET 6及以上版本,可以利用Keyed Service特性给每个实现打个标识,这样既能区分不同的接口实现,也能结合方案1的思路直接获取具体类:
// 给每个实现指定唯一Key services.AddKeyedSingleton<MyInterface, FirstImplementation>("first-implementation"); services.AddKeyedSingleton<MyInterface, SecondImplementation>("second-implementation"); // 同时注册实现类本身(如果需要直接获取的话) services.AddSingleton<FirstImplementation>(); services.AddSingleton<SecondImplementation>();
获取指定接口实现时可以用Key直接定位:
var firstImpl = serviceProvider.GetKeyedService<MyInterface>("first-implementation");
如果需要直接获取FirstImplementation实例,还是用serviceProvider.GetRequiredService<FirstImplementation>()即可。
为什么原来的方式不行?
当你调用services.AddSingleton<MyInterface, FirstImplementation>()时,DI容器只会记录“当请求MyInterface类型时,创建并返回FirstImplementation的实例”,但它不会把FirstImplementation本身作为一个独立的服务注册。所以当你直接请求FirstImplementation类型时,容器没有对应的注册信息,就会返回null。
你的遍历筛选方法虽然能解决问题,但代码冗余,而且如果需要频繁获取某个具体实现,这种方式既不高效也不优雅,上面的方案能更好地解决这个问题。
内容的提问来源于stack exchange,提问作者Yahya Hussein

