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>();
操作步骤:
- 启动应用
- 填充
ValueA和ValueB,ValueC未填充 - 用户登录后,尝试更新
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
相关产品推荐
相关产品推荐

