控制台应用依赖注入无法实例化泛型服务,获取服务均为null的原因
服务获取返回null的原因及修复方案
核心问题:使用了未配置服务的空容器
你在Main方法里创建了两个完全独立的ServiceCollection实例:
- 第一个
services实例已经通过ConfigureServices(services)完成了所有服务注册 - 但构建服务提供者时,却新建了一个空的
ServiceCollection来调用BuildServiceProvider(),这个空容器里没有任何你注册的服务,自然所有服务获取都会返回null。
错误代码片段:
// 这里新建了空容器,之前的服务配置完全没生效 var serviceProvider = new Microsoft.Extensions.DependencyInjection.ServiceCollection().BuildServiceProvider();
次要问题:配置顺序错误与多余操作
- AppSettings绑定顺序颠倒:你先调用
ConfigureServices把未填充配置的空AppSettings注册为单例,之后才用configuration.Bind加载配置,导致容器里的AppSettings是空对象(虽不是返回null的直接原因,但会引发后续逻辑问题)。 - ConfigureServices里多余的容器构建:方法末尾调用
services.BuildServiceProvider()毫无意义,这个返回的容器没被使用,还会额外创建容器实例。
修复后的代码示例
Main方法修正
static async Task<int> Main(string[] args) { var configuration = new ConfigurationBuilder() .AddJsonFile($"{Directory.GetCurrentDirectory()}//appsettings.json", false, true) .Build(); appSettings = new AppSettings(); // 先绑定配置,再注册服务 configuration.Bind("AppConfiguration", appSettings); var services = new ServiceCollection(); ConfigureServices(services); // 使用已经配置好的services实例构建容器 var serviceProvider = services.BuildServiceProvider(); var logger = serviceProvider.GetService<ILogger<Program>>(); var settings = serviceProvider.GetService<AppSettings>(); var service = serviceProvider.GetService<ServiceBase<Patient>>(); var patient = service.Create(); patient.PrimaryCarePhysician = "witch doctor"; return 1; }
ConfigureServices方法修正
public static void ConfigureServices(IServiceCollection services) { services.AddServiceLayer(); services.AddHttpClient(); services.AddHttpContextAccessor(); // 此时appSettings已加载配置,注册的是有值的实例 services.AddSingleton(appSettings); services.AddSingleton<JsonSerializerOptions>(new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); services.AddLogging(builder => { builder.ClearProviders(); builder.AddFile($"{Directory.GetCurrentDirectory()}\\Logs\\Log.txt"); // 修正反斜杠转义 builder.AddSimpleConsole(c => { c.TimestampFormat = "yyyy-MM-dd HH:mm:ss => "; c.SingleLine = true; }); }); services.AddTransient<IUnitOfWork, UnitOfWork>(); services.AddTransient<DbContext, ClientContext>(); services.AddTransient<ClientContext, ClientContext>(); services.AddTransient(typeof(ServiceBase<Patient>), typeof(ServiceBase<Patient>)); // 移除此处多余的services.BuildServiceProvider(); }
注意:日志路径里的反斜杠要转义,否则会被当作特殊字符处理,导致路径解析错误。
内容的提问来源于stack exchange,提问作者jrandomuser
相关产品推荐
相关产品推荐

