簡體   English   中英

如何將依賴注入與 [SwaggerOperationFilter] 一起使用?

[英]How to use Dependency Injection with [SwaggerOperationFilter]?

我正在使用 Swashbuckle 為我的 web api 實現 OpenAPI 文檔。 我決定在我的一項操作中使用[SwaggerOperationFilter]屬性,以改進其響應正文示例。

根據文檔,Swashbuckle 的過濾器管道可以使用依賴注入,根據以下摘錄:

注意:過濾器管道是 DI 感知的。 也就是說,您可以使用構造函數參數創建過濾器,如果參數類型已在 DI 框架中注冊,它們將在過濾器實例化時自動注入

這是 controller 的簡化版本

/// <summary>Some sample controller.</summary>
[ApiController]
[Route("/my-controller")]
public class MyController : ControllerBase {
    /// <summary>Simple action returning some string array.</summary>
    /// <response code="200">All went well.</response>
    [HttpGet]
    [SwaggerOperationFilter(typeof(MyOperationFilter))]
    public IEnumerable<string> GetSomeStrings() => new[] { "abc", "def" };
}

和我正在嘗試實現的IOperationFilter

public class MyOperationFilter : IOperationFilter {
    public MyOperationFilter(ILogger<MyOperationFilter> logger) {   // <--- Dependency Injection will fail to call this constructor
        logger.LogInformation("DI won't work!");
    }


    public void Apply(OpenApiOperation operation, OperationFilterContext context) {
        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;
    }
}

此代碼在嘗試訪問 OpenAPI 文檔和 Swagger UI 時無法執行,但出現以下異常:

MyProject.MyControllers.UnhandledExceptionsController[0]
      Unhandled exception of type SwaggerGeneratorException on path "/api-docs/my-api-v1/openapi.json"
      Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: Failed to generate Operation for action - MyProject.MyControllers.MyController.GetSomeStrings (my-project). See inner exception  
       ---> System.MissingMethodException: No parameterless constructor defined for type 'MyProject.MyControllers.MyOperationFilter'.
         at System.RuntimeType.CreateInstanceDefaultCtorSlow(Boolean publicOnly, Boolean wrapExceptions, Boolean fillCache)
         at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, Boolean wrapExceptions)
         at System.Activator.CreateInstance(Type type, Boolean nonPublic, Boolean wrapExceptions)
         at Swashbuckle.AspNetCore.Annotations.AnnotationsOperationFilter.ApplySwaggerOperationFilterAttributes(OpenApiOperation operation, OperationFilterContext context, IEnumerable`1 controllerAndActionAttributes)
         at Swashbuckle.AspNetCore.Annotations.AnnotationsOperationFilter.Apply(OpenApiOperation operation, OperationFilterContext context)
         at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperation(ApiDescription apiDescription, SchemaRepository schemaRepository)
         --- End of inner exception stack trace ---
         at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperation(ApiDescription apiDescription, SchemaRepository schemaRepository)
         at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperations(IEnumerable`1 apiDescriptions, SchemaRepository schemaRepository)
         at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GeneratePaths(IEnumerable`1 apiDescriptions, SchemaRepository schemaRepository)
         at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwagger(String documentName, String host, String basePath)
         at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
         at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)

我知道如果我在services.AddSwagerGen(...)調用中注冊IOperationFilter ,我的操作過濾器將啟用 DI 但是這種方法的問題是注冊的IOperationFilter將被注冊為“全局”過濾器,並將應用於我項目中的每個操作方法,我想避免這種情況,因為這個過濾器應該影響單個操作我項目中的方法。

有什么方法可以繼續使用本地(“非全局”) IOperationFilter (通過[SwaggerOperationFilter] )並讓我的過濾器注入依賴項?

有什么方法可以繼續使用本地(“非全局”) IOperationFilter (通過[SwaggerOperationFilter] )並讓我的過濾器注入依賴項?

不是根據他們的源代碼

注釋操作過濾器

//...

public static void ApplySwaggerOperationFilterAttributes(
    OpenApiOperation operation,
    OperationFilterContext context,
    IEnumerable<object> controllerAndActionAttributes)
{
    var swaggerOperationFilterAttributes = controllerAndActionAttributes
        .OfType<SwaggerOperationFilterAttribute>();

    foreach (var swaggerOperationFilterAttribute in swaggerOperationFilterAttributes)
    {
        var filter = (IOperationFilter)Activator.CreateInstance(swaggerOperationFilterAttribute.FilterType);
        filter.Apply(operation, context);
    }
}

//...

可以看出他們使用了Activator.CreateInstance ,這需要一個默認構造函數,正如給定異常的堆棧跟蹤中已經指出的那樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM