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

ASP.NET中为键控依赖注入注册多个DbCheck实例的问题

解决方案

1. 注册为接口集合(推荐)

因为你的DbCheck实现了ICheck接口,可以将三个实例都注册为ICheck的作用域服务,这样注入IEnumerable<ICheck>就能获取所有实例,再根据自定义标识区分:

// 注意给每个实例设置不同的checkName用于后续筛选
var db1 = new DbCheck("db1", dataConnection1, tableInfo1);
services.AddScoped<ICheck>(_ => db1);

var db2 = new DbCheck("db2", dataConnection2, tableInfo2);
services.AddScoped<ICheck>(_ => db2);

var db3 = new DbCheck("db3", dataConnection3, tableInfo3);
services.AddScoped<ICheck>(_ => db3);

使用时直接注入IEnumerable<ICheck>,遍历筛选需要的实例:

public class HealthChecker
{
    private readonly IEnumerable<ICheck> _dbChecks;

    public HealthChecker(IEnumerable<ICheck> dbChecks)
    {
        _dbChecks = dbChecks;
    }

    public void RunChecks()
    {
        var db1Check = _dbChecks.First(c => c.CheckName == "db1");
        db1Check.Execute();
        // 其他实例同理
    }
}

2. 正确使用键控依赖注入(.NET 6+)

你之前写的AddKeyedScoped参数形式有误,正确用法是将键作为第二个参数,工厂方法作为第三个参数(直接传入实例时可忽略服务提供者参数):

var db1 = new DbCheck(checkName, dataConnection, tableInfo);
services.AddKeyedScoped<DbCheck>("db1", _ => db1);

var db2 = new DbCheck(checkName, dataConnection, tableInfo);
services.AddKeyedScoped<DbCheck>("db2", _ => db2);

var db3 = new DbCheck(checkName, dataConnection, tableInfo);
services.AddKeyedScoped<DbCheck>("db3", _ => db3);

使用时通过[FromKeyedServices]特性注入,或手动从服务提供者获取:

// 构造函数注入方式
public class HealthChecker
{
    public HealthChecker([FromKeyedServices("db1")] DbCheck db1Check,
                         [FromKeyedServices("db2")] DbCheck db2Check)
    {
        // 使用实例
    }
}

// 手动获取方式
var db1Check = services.GetRequiredKeyedService<DbCheck>("db1");

注意:键控服务仅支持.NET 6及以上版本,项目版本过低则无法使用。

3. 自定义工厂类管理实例

如果受限于NuGet包约束,可创建工厂类封装所有DbCheck实例,通过键直接获取:

public class DbCheckFactory
{
    private readonly Dictionary<string, DbCheck> _checkInstances;

    public DbCheckFactory(DbCheck db1, DbCheck db2, DbCheck db3)
    {
        _checkInstances = new Dictionary<string, DbCheck>
        {
            {"db1", db1},
            {"db2", db2},
            {"db3", db3}
        };
    }

    public DbCheck GetCheck(string key)
    {
        if (_checkInstances.TryGetValue(key, out var check))
        {
            return check;
        }
        throw new KeyNotFoundException($"未找到键为 {key} 的DbCheck实例");
    }
}

注册时先分别注册三个DbCheck实例,再注册工厂:

var db1 = new DbCheck(checkName, dataConnection, tableInfo);
services.AddScoped(_ => db1);

var db2 = new DbCheck(checkName, dataConnection, tableInfo);
services.AddScoped(_ => db2);

var db3 = new DbCheck(checkName, dataConnection, tableInfo);
services.AddScoped(_ => db3);

services.AddScoped<DbCheckFactory>();

使用时注入工厂类,调用GetCheck方法获取实例:

public class HealthChecker
{
    private readonly DbCheckFactory _checkFactory;

    public HealthChecker(DbCheckFactory checkFactory)
    {
        _checkFactory = checkFactory;
    }

    public void RunDb1Check()
    {
        var db1Check = _checkFactory.GetCheck("db1");
        db1Check.Execute();
    }
}

关于NuGet包的疑问

继承DbCheck子类触发错误,大概率是NuGet包内部对DbCheck类型有约束(比如标记为sealed密封类,或内部逻辑仅识别原始DbCheck类型)。建议查看包的官方文档,或联系维护者确认是否支持多实例注册、是否有官方推荐的多数据库健康检查实现方式。

内容的提问来源于stack exchange,提问作者user19627737

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 18:35:04