如何在[SwaggerOperationFilter]特性中使用依赖注入?
问题根因
官方文档提及的过滤器支持依赖注入特性,仅针对在AddSwaggerGen方法中全局注册的IOperationFilter实例。通过[SwaggerOperationFilter]特性标注的过滤器,Swashbuckle底层会直接通过Activator.CreateInstance反射实例化,不会走DI容器解析,因此要求过滤器必须有公共无参构造函数,这就是你触发报错的核心原因。
推荐解决方案:全局过滤器+局部标记组合
该方案改动最小、稳定性最高,既保留了仅对指定接口生效的能力,又完全支持依赖注入:
步骤1:定义空标记特性
/// <summary> /// 标记指定接口/控制器需要应用MyOperationFilter /// </summary> [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)] public class ApplyMyFilterAttribute : Attribute { }
步骤2:修改OperationFilter逻辑,增加生效判断
public class MyOperationFilter : IOperationFilter { // 构造函数依赖注入保持不变 public MyOperationFilter(ILogger<MyOperationFilter> logger) { logger.LogInformation("依赖注入正常生效!"); } public void Apply(OpenApiOperation operation, OperationFilterContext context) { // 判断当前接口或所属控制器是否打了指定标记,未打标直接跳过 var needApply = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType<ApplyMyFilterAttribute>().Any() || context.MethodInfo.GetCustomAttributes(true).OfType<ApplyMyFilterAttribute>().Any(); if (!needApply) return; // 原有响应示例设置逻辑保持不变 var responseExample = new OpenApiArray(); responseExample.AddRange(new [] { new OpenApiString("text-1"), new OpenApiString("text-2"), new OpenApiString("text-3"), }); var response = operation.Responses["200"]; response.Content["application/json"].Example = responseExample; } }
步骤3:全局注册过滤器
在Program.cs(.NET 6+)或Startup.cs的Swagger配置中注册过滤器:
builder.Services.AddSwaggerGen(options => { // 全局注册该过滤器,因内部有生效判断,不会影响未打标的接口 options.OperationFilter<MyOperationFilter>(); // 其余Swagger配置保持不变 });
步骤4:在需要生效的接口上打标记
替换原有[SwaggerOperationFilter]特性即可:
[HttpGet] [ApplyMyFilter] public IEnumerable<string> GetSomeStrings() => new[] { "abc", "def" };
可选方案:服务定位器模式(不推荐)
如果一定要保留[SwaggerOperationFilter]特性的用法,可以通过服务定位器手动解析依赖,该方案不符合显式依赖原则,可测试性较差,且仅在Swagger文档随请求生成的场景下可用:
- 先注册HttpContextAccessor:
builder.Services.AddHttpContextAccessor();
- 修改过滤器实现:
public class MyOperationFilter : IOperationFilter { private readonly ILogger<MyOperationFilter> _logger; private readonly IHttpContextAccessor _httpContextAccessor; // 新增无参构造函数,手动解析依赖 public MyOperationFilter() { _httpContextAccessor = new HttpContextAccessor(); _logger = _httpContextAccessor.HttpContext.RequestServices.GetRequiredService<ILogger<MyOperationFilter>>(); } public void Apply(OpenApiOperation operation, OperationFilterContext context) { // 原有逻辑保持不变 } }
内容的提问来源于stack exchange,提问作者vinicius.ras
相关产品推荐
相关产品推荐

