ActivatorUtilities 是 .NET 内置的轻量级对象创建辅助类,它不替代
IServiceProvider,而是**在没有完整 DI 容器上下文时,按需解析依赖并构造对象**。它常用于中间件、策略、工厂等需要“局部依赖注入”的场景,是 .NET DI 生态中被低估但非常实用的高级工具。
用 ActivatorUtilities.CreateFactory 创建可复用的工厂
当你需要多次创建同一类型(比如每次 HTTP 请求都 new 一个策略实例),又不想每次都走
GetService<t>()</t>,可以用
CreateFactory预编译构造逻辑: 返回的是
Func<iserviceprovider t></iserviceprovider>,性能高,支持缓存 自动识别构造函数参数,支持带服务、常量、委托等混合注入 适合注册到 DI 容器中作为工厂方法,或在中间件中复用
示例:
var factory = ActivatorUtilities.CreateFactoryvar service = factory(provider, configuration); // provider 是 IServiceProvider
用 ActivatorUtilities.CreateInstance 按需构造临时对象
适用于“一次性的、非托管生命周期”的对象创建,比如在 Action 中动态构建验证器、映射器:
不需要类型提前注册到 DI 容器(但其依赖必须已注册) 支持传入部分参数(如字符串、int),其余由 DI 自动解析 比直接 new 更灵活,比 Resolve 更轻量示例:
var validator = ActivatorUtilities.CreateInstance配合 ServiceProviderServiceExtensions 扩展自定义服务解析逻辑
你可以给
IServiceProvider添加扩展方法,把
ActivatorUtilities封装成更语义化的 API: 例如
provider.CreateScopedInstance<t>(args...)</t>,内部调用
CreateInstance并确保作用域正确 可用于统一处理“带上下文参数 + 依赖注入”的构造场景 避免在业务代码里反复写冗长的 ActivatorUtilities 调用
注意事项和常见陷阱
ActivatorUtilities 强大但有边界,用错容易引发问题:
它不管理对象生命周期:创建出来的实例不会被 DI 容器跟踪,Dispose、Scope 释放等需手动处理 构造函数必须是 public,且不能有歧义(多个重载构造函数需显式指定) 如果依赖未注册,异常信息不如GetRequiredService友好,建议加 try/catch 或预检 在 Razor Pages 或 MVC 的
@inject场景中一般不需要它——直接用构造函数注入更清晰
基本上就这些。ActivatorUtilities 不是黑魔法,它是 DI 容器能力的自然延伸,用对了能让代码更松耦合、更易测试,也更贴近 .NET 原生设计哲学。
