Autofac如何不执行Resolve操作即可获取当前作用域内注册的实现类类型
解决方案
你可以通过 Autofac 内置的 ComponentRegistry 直接查询注册信息,全程不会触发服务实例化,性能开销极低,且自动适配子作用域的覆盖注册规则。
实现扩展方法
直接为 ILifetimeScope 实现你要求的 WhatTypeIsRegisteredFor<T> 扩展方法:
using Autofac; using Autofac.Core; using Autofac.Core.Registration; public static class LifetimeScopeExtensions { public static Type WhatTypeIsRegisteredFor<TService>(this ILifetimeScope scope) { var service = new TypedService(typeof(TService)); // 从当前作用域查询优先级最高的匹配注册,自动适配子作用域覆盖逻辑 if (scope.ComponentRegistry.TryGetServiceRegistration(service, out var registration)) { // 返回注册的实现类型,不会实例化任何服务 return registration.Activator.LimitType; } throw new ComponentNotRegisteredException(service); } }
调用方式
完全符合你要求的调用形式:
// 根容器、任意子作用域都可直接调用 var concreteType = scope.WhatTypeIsRegisteredFor<IBasicA>();
补充说明
- 该方法返回的类型和你实际调用
Resolve<IBasicA>()得到的实例类型完全一致,会自动优先取子作用域覆盖的注册,不会读取根容器的旧注册 - 全程不会触发服务实例化,也不会遍历服务的依赖链,性能损耗可以忽略,完美规避重型服务实例化的开销
- 兼容所有Autofac注册方式:不管是
RegisterType、Lambda注册、泛型注册还是实例注册,都能正确返回对应的实现类型
如果需要获取同一服务的所有注册实现类型,可以用以下重载:
public static IEnumerable<Type> WhatTypesAreRegisteredFor<TService>(this ILifetimeScope scope) { var service = new TypedService(typeof(TService)); return scope.ComponentRegistry .GetServiceRegistrationsFor(service) .Select(r => r.Activator.LimitType); }
内容的提问来源于stack exchange,提问作者Rhyous
相关产品推荐
相关产品推荐

