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

C#如何跨库边界在IServiceCollection中构建可扩展的服务集合

跨库向ServiceCollection注册共享集合对象的解决方案

核心思路

.NET 自带的依赖注入容器天然支持同一接口的多实现注册+自动聚合解析,不需要手动维护固定实例的集合,即可实现跨库扩展。

推荐方案:使用原生集合注入能力

这是最简洁、符合DI规范的实现方式,不需要额外封装:

  1. 库作者端注册逻辑:
    不要直接注册写死实例的List<ICommand>,改为逐个注册你内置的ICommand实现:
// 库内注册代码
services.AddSingleton<ICommand, Command1>();
services.AddSingleton<ICommand, Command2>();
// 其他内置Command同理逐个注册
  1. 库内使用逻辑:
    需要用到所有Command的位置,构造函数注入IEnumerable<ICommand>即可,DI会自动聚合所有注册过的ICommand实现(包括库外用户注册的),如果需要使用List类型直接转换即可:
public class YourCoreService
{
    private readonly List<ICommand> _allCommands;

    public YourCoreService(IEnumerable<ICommand> commands)
    {
        _allCommands = commands.ToList();
    }
}
  1. 库使用者扩展逻辑:
    用户只需要在自己的项目中注册自定义的ICommand实现,就会被自动纳入集合:
// 使用者端注册代码
services.AddSingleton<ICommand, UserCustomCommand>();
services.AddSingleton<ICommand, AnotherUserCommand>();

进阶方案:封装扩展方法做统一校验

如果你需要对用户注册的ICommand做统一校验、附加初始化逻辑,可以对外暴露扩展方法:

// 你库内对外提供的扩展方法
public static IServiceCollection AddCommand<TCommand>(this IServiceCollection services) 
    where TCommand : class, ICommand
{
    // 此处可添加自定义校验逻辑,比如检查实现是否符合要求、是否重复注册等
    services.AddSingleton<ICommand, TCommand>();
    return services;
}

用户使用时直接调用扩展方法即可:

services.AddCommand<UserCustomCommand>();

特殊场景方案:必须共用同一个单例List实例

如果业务要求必须持有同一个全局List<ICommand>单例,可通过托管服务实现注入:

// 库内先注册空的单例List
services.AddSingleton<List<ICommand>>();

// 注册Command的扩展方法
public static IServiceCollection AddCommand<TCommand>(this IServiceCollection services)
    where TCommand : class, ICommand
{
    services.AddSingleton<TCommand>();
    // 借助托管服务在服务启动时将实例添加到全局List
    services.AddHostedService(sp => 
    {
        var globalList = sp.GetRequiredService<List<ICommand>>();
        var commandInstance = sp.GetRequiredService<TCommand>();
        globalList.Add(commandInstance);
        return EmptyHostedService.Instance;
    });
    return services;
}

// 空托管服务占位实现
internal class EmptyHostedService : IHostedService
{
    public static readonly EmptyHostedService Instance = new();
    public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
    public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}

内置Command和用户自定义Command都通过上述AddCommand扩展方法注册,即可全部添加到同一个单例List中。

通用逻辑总结:跨库构建共享对象的核心是避免直接硬编码构造固定实例注册,将构造权限开放给DI容器,通过逐个注册依赖项、由容器统一组合的方式实现无侵入式扩展,所有编译期可知的实现都可以适配这套逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 03:15:04