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

DryIoc C#:如何更新已注入的服务实例?

问题:DryIoc中如何更新已注入的服务实例?

场景还原

应用启动时注册服务:

public class MyService:IMyService
{
  public string ValueAPopulatedBeforeLogin { get; set; }
  public string ValueBPopulatedBeforeLogin { get; set; }
  public string ValueCPopulatedAfterLogin { get; set; }
}
container.Register<IMyService, MyService>();

操作步骤:

  1. 启动应用
  2. 填充ValueA和ValueB,ValueC未填充
  3. 用户登录后,尝试更新MyService的ValueC并替换容器中的实例:
container.ClearCache(typeof(IMyService));
container.UseInstance(myUpdatedService); // myUpdatedService为已填充ValueC的实例

遇到的问题:

  • 重新解析IMyService能拿到新实例(使用IfAlreadyRegistered.Replace语法后)
  • 已注入到其他服务中的IMyService实例未更新,仍为旧实例

用户疑问:是否真的无法修改已注入的服务实例,只能通过重新解析获取新实例?


解答

首先明确:已经注入到其他服务中的实例确实无法被容器自动替换。因为容器解析依赖时,会将实例直接注入到目标服务的构造函数/属性中,目标服务持有该实例的独立引用,容器无法追溯并替换所有已分发的引用。

但可以通过以下几种方案实现类似"更新"的效果,满足登录后刷新数据的需求:

1. 使用可更新的包装类

定义包装类持有IMyService实例,将包装类注入到其他服务中,登录后更新包装类内的实例:

public class MyServiceWrapper : IMyServiceWrapper
{
    public IMyService Current { get; set; }
}

// 启动时注册
container.Register<IMyServiceWrapper, MyServiceWrapper>(Reuse.Singleton);
var initialService = new MyService { ValueA = "a", ValueB = "b" };
container.Resolve<IMyServiceWrapper>().Current = initialService;

// 登录后更新
var updatedService = new MyService { ValueA = "a", ValueB = "b", ValueC = "c" };
container.Resolve<IMyServiceWrapper>().Current = updatedService;

其他服务注入IMyServiceWrapper,通过wrapper.Current获取最新的IMyService实例。

2. 使用工厂模式延迟解析

注册工厂委托,让依赖服务每次需要IMyService时都从容器获取最新实例:

// 注册工厂
container.Register<Func<IMyService>>(r => () => r.Resolve<IMyService>(), Reuse.Singleton);

// 依赖服务注入Func<IMyService>
public class DependentService
{
    private readonly Func<IMyService> _myServiceFactory;
    public DependentService(Func<IMyService> myServiceFactory)
    {
        _myServiceFactory = myServiceFactory;
    }

    public void DoSomething()
    {
        var latestService = _myServiceFactory();
        // 使用最新实例
    }
}

// 登录后更新注册
container.RegisterInstance<IMyService>(updatedService, ifAlreadyRegistered: IfAlreadyRegistered.Replace);
container.ClearCache(typeof(IMyService));

3. 使用作用域隔离

如果登录是应用生命周期的分界点,可在登录后创建新作用域,在新作用域内注册更新后的IMyService,后续服务解析均使用新作用域:

// 启动时创建根作用域
using var rootScope = container.OpenScope();
var initialService = new MyService { ValueA = "a", ValueB = "b" };
rootScope.UseInstance(initialService);

// 登录后创建新作用域
using var postLoginScope = container.OpenScope();
var updatedService = new MyService { ValueA = "a", ValueB = "b", ValueC = "c" };
postLoginScope.UseInstance(updatedService);

// 后续解析服务使用新作用域
var dependentService = postLoginScope.Resolve<DependentService>();

关键结论

  • 已分发到其他服务中的实例引用无法被容器直接替换,因目标服务持有独立引用
  • 要实现"更新"效果,需通过间接引用(包装类、工厂)或作用域隔离的方式,让依赖服务能获取到最新实例

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 18:55:14