使用Unity依赖注入时无法解析ISwaggerProvider的问题求助
问题描述
开发ASP.NET Core 8.0应用时,使用Swashbuckle.AspNetCore(v7.2.0)集成Swagger,同时采用Unity(v5.11.10)+ Unity.Microsoft.DependencyInjection(v5.11.5)作为DI容器替代默认DI,加载Swagger UI或调用API时抛出错误:
Unable to resolve service for type 'Swashbuckle.AspNetCore.Swagger.ISwaggerProvider' while attempting to Invoke middleware 'Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware'.
移除builder.Host.UseUnityServiceProvider(unityContainer)后Swagger可正常运行,且ISwaggerProvider能被Unity单独解析,但中间件调用时仍报错。
Program.cs核心配置如下:
var builder = WebApplication.CreateBuilder(args); var unityContainer = new UnityContainer(); builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddControllers().AddControllersAsServices(); builder.Services.AddControllersWithViews(); UnityConfig.RegisterTypes(unityContainer); builder.Host.UseUnityServiceProvider(unityContainer); // 此行导致Swagger报错 var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.MapControllers(); app.Run();
核心原因
AddSwaggerGen()会将Swagger相关服务(包括ISwaggerProvider)注册到ASP.NET Core原生DI容器中,但Unity默认不会自动同步原生DI的注册项。当使用UseUnityServiceProvider替换根服务提供者后,Unity容器中缺少Swagger的服务注册,导致中间件从根容器解析依赖时失败。
解决方案
方案1:同步原生DI服务到Unity容器
在注册自定义服务前,将原生DI中所有已注册的服务导入到Unity容器,确保Swagger的服务被包含在内:
var builder = WebApplication.CreateBuilder(args); var unityContainer = new UnityContainer(); // 1. 先注册所有原生DI服务(包括Swagger) builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddControllers().AddControllersAsServices(); builder.Services.AddControllersWithViews(); // 2. 将原生DI的服务同步到Unity容器 unityContainer.RegisterServices(builder.Services); // 3. 注册自定义服务 UnityConfig.RegisterTypes(unityContainer); // 4. 设置Unity为根服务提供者 builder.Host.UseUnityServiceProvider(unityContainer); var app = builder.Build(); // 后续管道配置不变 if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.MapControllers(); app.Run();
方案2:手动注册Swagger核心服务到Unity
如果不需要同步所有原生DI服务,可手动将Swagger的关键服务注册到Unity容器(需确保所有依赖链完整):
在UnityConfig.RegisterTypes方法中添加:
// 注册Swagger核心服务 container.RegisterType<ISwaggerProvider, SwaggerGenerator>(new ContainerControlledLifetimeManager()); container.RegisterType<ISchemaGenerator, SchemaGenerator>(new ContainerControlledLifetimeManager()); // 根据Swashbuckle版本,可能还需要注册其他相关服务(如IDocumentFilter、IOperationFilter等)
针对疑问的解答
Swashbuckle与Unity的已知问题:
两者本身无直接兼容性问题,核心问题出在Unity与ASP.NET Core原生DI的整合逻辑上——Unity默认不会自动继承原生DI的服务注册,需手动同步Swashbuckle的服务到Unity容器。Unity集成到中间件管道的配置限制:
- 替换根服务提供者后,所有中间件、控制器的依赖必须能被Unity容器解析;
- 中间件的构造函数依赖是从根服务提供者获取的,因此Unity容器必须包含所有中间件所需的服务;
- 需确保Unity作为服务提供者的配置步骤在所有原生DI服务注册之后,避免遗漏服务。
确保SwaggerMiddleware解析ISwaggerProvider的关键:
必须让Unity容器中存在ISwaggerProvider的有效注册,最可靠的方式是通过RegisterServices同步原生DI的所有注册项,或手动注册Swagger的完整服务链,避免遗漏依赖导致解析失败。
内容的提问来源于stack exchange,提问作者DotNET Developer

