ASP.NET Core MVC 过滤器是单例吗?

Sco*_*.Hu 5 c# asp.net-core

我有一个 AuthorizationFilter 如下:

public class AuthorizationFilterAttribute : Attribute, IAuthorizationFilter
{
    public AuthorizationFilterAttribute()
    {
        //Constructor of AuthorizationFilter will be called one time
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        //OnAuthorization method will be called per http request
    }
}
Run Code Online (Sandbox Code Playgroud)

我发现 AuthorizationFilter 的构造函数在整个 ASP.NET Core 应用程序生命周期中只会被调用一次。但是它的 OnAuthorization 方法将在每个 HTTP 请求中被调用。

这是否意味着所有的过滤器(包括IAuthorizationFilterIActionFilterIResourceFilterIExceptionFilter等)在ASP.NET MVC的核心是单身,这意味着他们将ASP.NET的核心应用生命周期过程中创建只是一个时间?

hai*_*770 7

这取决于IFilterFactory.IsReusable与您的过滤器关联的属性。

IFilterProvider(默认情况下是DefaultFilterProvider) 即将提供所需的实例时,它首先检查过滤器是否也实现IFilterFactory了:

  • 如果是,它使用过滤器自己的IsReusable属性来确定实例的生命周期。
  • 如果没有,它假定过滤器可重复使用,并IsReusable设置为 true

在您的 custom 的情况下AuthorizationFilterAttribute,由于您没有实现IFilterProvider,它确实被认为是可重用的,并且只会创建一次。

查看来源


Sco*_*.Hu 5

感谢haim770的回答。

我发现了一个可以为每个 http 请求而不是 ASP.NET Core 应用程序生命周期创建一个过滤器实例的实现。

实际上,我们需要在内部创建过滤器并将其包装到 IFilterFactory 中,如下所示:

using Microsoft.AspNetCore.Mvc.Filters;
using System;

namespace AspNetCoreFilterDemo.Filters
{
    public class AuthorizationFilterWithFactoryAttribute : Attribute, IFilterFactory
    {
        //Return false, IFilterFactory.CreateInstance method will be called per http request
        //Return true, InternalAuthorizationFilter will still be singleton, since IFilterFactory.CreateInstance will be called only one time during the whole ASP.NET Core application lifetime
        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

        private class InternalAuthorizationFilter : IAuthorizationFilter
        {
            public InternalAuthorizationFilter()
            {
                //This InternalAuthorizationFilter constructor will be called per http request rather than ASP.NET Core application lifetime
            }

            public void OnAuthorization(AuthorizationFilterContext context)
            {
                //OnAuthorization method will be called per http request
            }
        }

        public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
        {
            //Create InternalAuthorizationFilter instance per http request
            return new InternalAuthorizationFilter();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意IFilterFactory.IsReusable属性,我们需要返回 false,否则该IFilterFactory.CreateInstance方法将在 ASP.NET Core 应用程序生命周期内仅被调用一次,并且InternalAuthorizationFilter仍然是单例的。

然后,我们需要指定AuthorizationFilterWithFactoryAttributeoncontroller而不是InternalAuthorizationFilter,但AuthorizationFilterWithFactoryAttribute实际上会为每个 http 请求创建一个InternalAuthorizationFilter实例并对其进行操作:

using Microsoft.AspNetCore.Mvc;
using AspNetCoreFilterDemo.Filters;

namespace AspNetCoreFilterDemo.Controllers
{
    public class HomeController : Controller
    {
        public HomeController()
        {

        }

        [AuthorizationFilterWithFactory]
        public IActionResult Index()
        {
            return View();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

AuthorizationFilterWithFactoryAttribute仍将是单例且创建一次,但我们接近目标以针对InternalAuthorizationFilter每个 http 请求创建过滤器 ( )。

您也可以从MSDN获取参考。