依赖注入中如何获取服务密钥,实现同键服务自动注入?
解决方法
要实现类A注入与自身相同服务密钥的类B,你无法直接通过[FromKeyedServices]属性动态获取当前服务密钥(因为属性参数必须是编译时常量),但可以通过以下两种方式解决:
1. 使用工厂注册方式(推荐)
在注册键控服务时,利用工厂方法捕获当前服务密钥,显式解析对应密钥的B实例并注入到A中。
修改你的扩展方法:
public static class ServiceCollectionExtensions { public static void AddKeyedA(this IServiceCollection serviceCollection, string serviceKey) { // 先注册B的键控实例 serviceCollection.AddKeyedSingleton<B>(serviceKey); // 使用工厂方法注册A,捕获服务密钥并解析对应B serviceCollection.AddKeyedSingleton<A>(serviceKey, (serviceProvider, currentKey) => { var b = serviceProvider.GetRequiredKeyedService<B>(currentKey); return new A(b); }); } }
这样,当解析密钥为abc的A时,工厂会自动用同一个密钥abc获取B的实例,再传递给A的构造函数。A的构造函数无需修改,保持原来的形式即可:
class A { private readonly B _b; public A(B b) { _b = b; } }
2. 注入服务密钥与IServiceProvider(按需使用)
如果需要在A内部动态使用服务密钥(比如后续解析其他键控服务),可以将服务密钥和IServiceProvider注入到A的构造函数中:
首先修改A的构造函数:
class A { private readonly B _b; private readonly string _serviceKey; private readonly IServiceProvider _serviceProvider; public A(IServiceProvider serviceProvider, string serviceKey) { _serviceKey = serviceKey; _serviceProvider = serviceProvider; _b = serviceProvider.GetRequiredKeyedService<B>(serviceKey); } }
然后在注册时,通过工厂传递服务密钥:
public static void AddKeyedA(this IServiceCollection serviceCollection, string serviceKey) { serviceCollection.AddKeyedSingleton<B>(serviceKey); serviceCollection.AddKeyedSingleton<A>(serviceKey, (sp, key) => new A(sp, key)); }
这种方式适合需要在A的方法中动态解析其他同密钥服务的场景,但不如第一种方式直接依赖注入B清晰。
关键说明
- .NET的键控服务系统没有内置的“当前服务密钥”获取机制,因为属性参数必须是编译时常量,无法动态传递运行时的密钥值。
- 工厂注册是最直接的解决方案,它允许你在注册阶段捕获服务密钥,并显式解析对应依赖。
内容的提问来源于stack exchange,提问作者user606521
相关产品推荐
相关产品推荐

