.NET非构造注入场景下,如何获取Program.cs已注册类实例
解决方案
1. 保留服务提供者引用
在Program.cs中,将构建完成的IServiceProvider保存到一个可全局访问的静态类中,用于后续实例获取:
var builder = WebApplication.CreateBuilder(args); // 根据需求注册服务(仅选择一种生命周期) builder.Services.AddSingleton<MyClass>(); // builder.Services.AddTransient<MyClass>(); // builder.Services.AddScoped<MyClass>(); // 注册接口与对应实现(支持动态获取场景) builder.Services.AddTransient<IMyClass, MyClassA>(); builder.Services.AddTransient<IMyClass, MyClassB>(); var app = builder.Build(); // 将ServiceProvider注入静态定位器 ServiceLocator.Instance = app.Services; // 后续中间件配置... app.Run();
2. 实现ServiceLocator静态类
创建轻量静态类封装实例获取逻辑,供旧代码直接调用:
public static class ServiceLocator { // 全局服务提供者实例 public static IServiceProvider Instance { get; set; } /// <summary> /// 泛型方式获取实例 /// </summary> public static T GetInstance<T>() { return Instance.GetRequiredService<T>(); } /// <summary> /// 按Type类型获取实例(匹配需求中的GetInstance(Type)场景) /// </summary> public static object GetInstance(Type type) { return Instance.GetRequiredService(type); } }
3. 在旧代码中获取实例
直接获取指定类型实例
// 对应你期望的调用方式 MyClass myInstance = (MyClass)ServiceLocator.GetInstance(typeof(MyClass)); // 泛型方式更简洁 MyClass myInstance = ServiceLocator.GetInstance<MyClass>();
动态获取接口的不同实现
public void MyFunc(string className) { // 需传入完整命名空间+类名,跨程序集需追加程序集名称(如:myNamespace.MyClass, MyAssembly) var type = Type.GetType($"myNamespace.{className}"); if (type == null) { throw new ArgumentException($"未找到目标类型:myNamespace.{className}"); } IMyClass myClass = (IMyClass)ServiceLocator.GetInstance(type); myClass.DoSomething(); }
4. 处理Scoped生命周期服务
Scoped服务必须在作用域内使用,若旧代码不在请求作用域(如后台任务、离线脚本),需手动创建临时作用域:
// 创建临时作用域 using var scope = ServiceLocator.Instance.CreateScope(); var scopedProvider = scope.ServiceProvider; // 在作用域内获取Scoped实例 var scopedInstance = scopedProvider.GetRequiredService<MyClass>(); // 使用实例...
注意事项
- 过渡方案提示:ServiceLocator是重构过渡期的妥协方案,完成代码重构后务必替换为构造注入,避免服务定位器反模式带来的维护隐患
- Type.GetType限制:目标类不在当前程序集时,需指定完整程序集名称,格式为
命名空间.类名, 程序集名称 - 异常处理:可根据业务需求将
GetRequiredService替换为GetService,并处理实例为null的情况(GetRequiredService在找不到实例时会抛出异常)
内容的提问来源于stack exchange,提问作者Platypus
相关产品推荐
相关产品推荐

