DryIoC如何实现IsResolved检测当前作用域服务是否已实例化
如何在DryIoC当前作用域内检查指定服务是否已被创建
DryIoC原生确实没有直接提供IsResolved方法,但可以通过它公开的作用域缓存访问API实现完全等价的判断逻辑,整个过程不会触发服务实例化,完全符合预期需求。
注意:该判断逻辑仅对单例(Reuse.Singleton)、作用域单例(Reuse.Scoped)生命周期的服务生效。瞬态(Reuse.Transient)服务每次解析都会生成新实例,不会存入作用域缓存,本身不存在“已创建可复用”的语义,因此判断对瞬态服务始终返回false,符合容器生命周期设计。
实现代码
首先定义静态扩展方法,直接复用DryIoC公开的作用域缓存读取能力,不需要反射,性能和原生API一致:
using DryIoc; public static class DryIocExtensions { public static bool IsResolved<TService>(this IResolverContext resolver) { return resolver.IsResolved(typeof(TService)); } public static bool IsResolved(this IResolverContext resolver, Type serviceType, object serviceKey = null) { // 先检查服务是否完成注册,未注册直接返回false var registrations = resolver.GetServiceRegistrations() .Where(r => r.ServiceType == serviceType && Equals(r.ServiceKey, serviceKey)) .ToList(); if (registrations.Count == 0) return false; // 获取当前上下文对应的作用域,根容器对应根作用域 var currentScope = resolver.CurrentScope ?? resolver.RootScope; if (currentScope == null) return false; // 遍历注册项,直接从作用域缓存读取已存在实例,不触发创建逻辑 foreach (var reg in registrations) { if (currentScope.TryGet(reg.Factory.InstanceCacheKey, out _)) { return true; } } return false; } }
使用示例
用法和预期写法完全一致:
var container = new Container(); container.Register<S>(Reuse.Scoped); // 也支持Reuse.Singleton生命周期 // 服务解析前判断,返回false if (container.IsResolved<S>()) { // 解析前不会进入该分支 } var s = container.Resolve<S>(); // 服务解析后判断,返回true if (container.IsResolved<S>()) { // 解析后会进入该分支 }
嵌套作用域场景下,判断会自动限定在当前作用域范围内,不会跨作用域误判:
var container = new Container(); container.Register<S>(Reuse.Scoped); using (var outerScope = container.OpenScope()) { var outerS = outerScope.Resolve<S>(); Console.WriteLine(outerScope.IsResolved<S>()); // 输出:True using (var innerScope = outerScope.OpenScope()) { Console.WriteLine(innerScope.IsResolved<S>()); // 输出:False,内层作用域尚未解析S var innerS = innerScope.Resolve<S>(); Console.WriteLine(innerScope.IsResolved<S>()); // 输出:True } }
带服务Key的注册场景,调用IsResolved时传入对应serviceKey参数即可完成判断。
内容的提问来源于stack exchange,提问作者emdadgar2
相关产品推荐
相关产品推荐

