簡體   English   中英

如何在 asp.net 核心操作過濾器中使用依賴注入?

[英]How can I use dependency injection in asp.net core action filter?

我有一個FilterAttribute,它有兩個參數,一個在依賴注入中定義,一個在控制器方法上定義為字符串

public controller : ControllerBase 
{
    [MyFilter("Parameter1", FromDependency)]
    public ActionResult MyMethod()
    {
         ....
    }
}

和過濾器

public MyFilter : Attribute
{
    MyFilter(string parameter1, context fromDependency)
    {
    }
}

如何從依賴注入中注入參數?

您可以為此目的實現IFilterFactory 運行時在創建過濾器時檢查此接口並調用獲取IServiceProvider作為參數的CreateInstance方法。 您可以使用此提供程序創建服務並將它們注入過濾器。

以下示例取自文檔

public class ResponseHeaderFilterFactory : Attribute, IFilterFactory
{
    public bool IsReusable => false;

    public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) =>
        new InternalResponseHeaderFilter();

    private class InternalResponseHeaderFilter : IActionFilter
    {
        public void OnActionExecuting(ActionExecutingContext context) =>
            context.HttpContext.Response.Headers.Add(
                nameof(OnActionExecuting), nameof(InternalResponseHeaderFilter));

        public void OnActionExecuted(ActionExecutedContext context) { }
    }
}

如果您需要同時使用 DI 中的服務和屬性上定義的值,則可以使用以下方法:

public class ResponseHeaderFilterFactory : Attribute, IFilterFactory
{
    private readonly string _attrParam;

    public ResponseHeaderFilterFactory(string attrParam)
    {
      _attrParam = attrParam;
    }

    public bool IsReusable => false;

    public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) 
    {
        var svc = serviceProvider.GetRequiredService<IMyService>();
        return new InternalResponseHeaderFilter(_attrParam, svc);
    }

    private class InternalResponseHeaderFilter : IActionFilter
    {
        private readonly string _attrParam;
        private readonly IMyService _service;

        public InternalResponseHeaderFilter(string attrParam, IMyService service)
        {
          _attrParam = attrParam;
          _service = service;
        }

        public void OnActionExecuting(ActionExecutingContext context) =>
            context.HttpContext.Response.Headers.Add(
                nameof(OnActionExecuting), nameof(InternalResponseHeaderFilter));

        public void OnActionExecuted(ActionExecutedContext context) { }
    }
}

然后,您可以像這樣應用過濾器:

public controller : ControllerBase 
{
    [ResponseHeaderFilterFactory("Parameter1")]
    public ActionResult MyMethod()
    {
         ....
    }
}

您可以實現ActionFilterAttribute以從HttpContext.RequestServices獲取 DI 依賴項:

public sealed class MyAttr : ActionFilterAttribute
{
    MyAttr(string parameter1)
    {
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        //Get dependency from HttpContext services
        var myDependency = context.HttpContext.RequestServices.GetService<MyDependency>();

        //Use it
        myDependency.DoSomething();

        //....
    }
}

直接將組件注入到動作過濾器屬性中是不可能的,但是有各種變通方法可以讓我們有效地完成同樣的事情。 使用 ServiceFilter 是一種允許將依賴項注入到單個操作過濾器中的相對干凈的方法。

ServiceFilter 屬性可以在操作或控制器級別使用。 用法非常簡單:

[ServiceFilter(typeof(MyFilter))]

還有我們的過濾器:

public class MyFilter: IActionFilter
 { 
    MyFilter(string parameter1, context fromDependency)
    {
    }
 }

顯然,當我們從 IoC 容器解析過濾器時,我們需要注冊它:

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddScoped<MyFilter>(x => 
    new Service(x.GetRequiredService<IOtherService>(),
            "parameter1"));
    ...
}

Paul Hiles 文章中的更多詳細信息: 這里

暫無
暫無

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

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