You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

依赖注入中如何获取服务密钥,实现同键服务自动注入?

解决方法

要实现类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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 02:07:27