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

.NET Core能否重置DI容器?多站点Singleton实例更新需求

无需重置DI容器的Site实例更新方案

ASP.NET Core的默认DI容器(ServiceProvider)是启动时一次性构建的,运行时无法重置或重建,强行通过反射修改内部状态会引发线程安全问题和稳定性风险,所以直接重置容器的思路不可行。下面是无需改动现有Singleton服务结构的替代方案:

1. 用可更新的代理类包装Site实例

不要直接注册Site为Singleton,而是创建一个代理类ISiteProvider,内部持有可动态更新的Site实例,通过线程安全的方式实现刷新:

定义代理接口与实现

public interface ISiteProvider
{
    // 获取当前有效的Site实例
    Site CurrentSite { get; }
    // 触发Site实例刷新
    void RefreshSite();
}

public class SiteProvider : ISiteProvider
{
    private readonly IConfiguration _config;
    private readonly SomeDatabaseService _dbService;
    private Site _currentSite;
    private readonly object _refreshLock = new object();

    public SiteProvider(IConfiguration config, SomeDatabaseService dbService)
    {
        _config = config;
        _dbService = dbService;
        // 初始化加载Site数据
        _currentSite = LoadSiteFromDb();
    }

    public Site CurrentSite => _currentSite;

    public void RefreshSite()
    {
        lock (_refreshLock)
        {
            _currentSite = LoadSiteFromDb();
        }
    }

    private Site LoadSiteFromDb()
    {
        short siteId = _config.GetValue<short>("CoreSettings:SiteID");
        return _dbService.GetSite(siteId);
    }
}

注册代理类为Singleton

builder.Services.AddSingleton<ISiteProvider, SiteProvider>();

修改依赖处

所有原本直接注入Site的服务,改为注入ISiteProvider,通过provider.CurrentSite获取最新实例。比如:

// 原来的代码
public class SomeSingletonService
{
    public SomeSingletonService(Site site)
    {
        // ...
    }
}

// 修改后
public class SomeSingletonService
{
    private readonly ISiteProvider _siteProvider;
    public SomeSingletonService(ISiteProvider siteProvider)
    {
        _siteProvider = siteProvider;
        // 使用时取_currentSite = _siteProvider.CurrentSite
    }
}

手动触发刷新的API

添加一个带权限验证的后台接口,用于手动触发Site实例更新:

[ApiController]
[Route("internal")]
[Authorize(Roles = "SystemAdmin")]
public class SiteRefreshController : ControllerBase
{
    private readonly ISiteProvider _siteProvider;

    public SiteRefreshController(ISiteProvider siteProvider)
    {
        _siteProvider = siteProvider;
    }

    [HttpPost("refresh-site")]
    public IActionResult Refresh()
    {
        _siteProvider.RefreshSite();
        return Ok("Site instance refreshed successfully");
    }
}

2. 可选:自动定时刷新

如果需要自动检测更新,可以实现一个IHostedService定期检查数据库中Site的修改时间,自动触发刷新:

public class AutoSiteRefreshService : BackgroundService
{
    private readonly ISiteProvider _siteProvider;
    private readonly SomeDatabaseService _dbService;
    private readonly IConfiguration _config;
    private DateTime _lastCheckedTime = DateTime.UtcNow;

    public AutoSiteRefreshService(ISiteProvider siteProvider, SomeDatabaseService dbService, IConfiguration config)
    {
        _siteProvider = siteProvider;
        _dbService = dbService;
        _config = config;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        // 每30分钟检查一次
        while (!stoppingToken.IsCancellationRequested)
        {
            short siteId = _config.GetValue<short>("CoreSettings:SiteID");
            var latestUpdateTime = await _dbService.GetSiteLastModifiedTime(siteId);
            
            if (latestUpdateTime > _lastCheckedTime)
            {
                _siteProvider.RefreshSite();
                _lastCheckedTime = latestUpdateTime;
            }

            await Task.Delay(TimeSpan.FromMinutes(30), stoppingToken);
        }
    }
}

注册这个后台服务:

builder.Services.AddHostedService<AutoSiteRefreshService>();

方案优势

  • 无需修改现有Singleton服务的生命周期,避免了Scoped带来的DI开销和大量代码改动
  • 线程安全的刷新逻辑,不会影响正在运行的业务
  • 支持手动触发和自动定时刷新,无需重启应用池即可更新Site实例

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 05:48:24