简体   繁体   English

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

[英]Is ASP.NET Core MVC filter singleton?

I have an AuthorizationFilter as follows:我有一个 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
    }
}

I found the constructor of AuthorizationFilter will just be called one time during the whole ASP.NET Core application lifetime.我发现 AuthorizationFilter 的构造函数在整个 ASP.NET Core 应用程序生命周期中只会被调用一次。 But its OnAuthorization method will be called per HTTP request.但是它的 OnAuthorization 方法将在每个 HTTP 请求中被调用。

Does it mean all filters (including IAuthorizationFilter , IActionFilter , IResourceFilter , IExceptionFilter etc) in ASP.NET Core MVC are singletons, which means they will be created just one time during ASP.NET Core application lifetime?这是否意味着 ASP.NET Core MVC 中的所有过滤器(包括IAuthorizationFilterIActionFilterIResourceFilterIExceptionFilter等)都是单例,这意味着它们将在 ASP.NET Core 应用程序生命周期内只创建一次?

It depends on the IFilterFactory.IsReusable property that is associated with your filter.它取决于与过滤器关联的IFilterFactory.IsReusable属性。

When the IFilterProvider (which by default is DefaultFilterProvider ) is about to provide the desired instance, it first checks whether the filter implements IFilterFactory as well:IFilterProvider (默认为DefaultFilterProvider )即将提供所需的实例时,它首先检查过滤器是否也实现了IFilterFactory

  • If it does, it uses the filter's own IsReusable property to determine the lifetime of the instance.如果是,它使用过滤器自己的IsReusable属性来确定实例的生命周期。
  • If not, it assumes the filter is reusable and IsReusable is set to true .如果不是,则假定过滤器可重用的,并且IsReusable设置为true

In the case of your custom AuthorizationFilterAttribute , since you don't implement IFilterProvider , it's indeed considered as reusable and will be created only once.在您自定义AuthorizationFilterAttribute的情况下,由于您没有实现IFilterProvider ,它确实被认为是可重用的,并且只会创建一次。

See Source查看来源

Thanks for haim770's answer.感谢 haim770 的回答。

I found an implementation that can create a filter instance per http request rather than ASP.NET Core application lifetime.我找到了一个实现,它可以为每个 http 请求而不是 ASP.NET Core 应用程序生命周期创建一个过滤器实例。

Actually, we need to create the filter internally and wrap it into an IFilterFactory like below:实际上,我们需要在内部创建过滤器并将其包装到 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();
        }
    }
}

Please be aware of IFilterFactory.IsReusable property, we need to return false, otherwise the IFilterFactory.CreateInstance method will be called only one time during ASP.NET Core application lifetime, and InternalAuthorizationFilter is still singleton.请注意IFilterFactory.IsReusable属性,我们需要返回 false,否则IFilterFactory.CreateInstance方法在 ASP.NET Core 应用程序生命周期InternalAuthorizationFilter只会被调用一次,并且InternalAuthorizationFilter仍然是单例。

Then, we need to specify the AuthorizationFilterWithFactoryAttribute on controller instead of InternalAuthorizationFilter , but AuthorizationFilterWithFactoryAttribute will actually create and operate on an InternalAuthorizationFilter instance per http request:然后,我们需要在controller上指定AuthorizationFilterWithFactoryAttribute而不是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();
        }
    }
}

AuthorizationFilterWithFactoryAttribute will still be singleton and created one time, but we approached the target to create the filter ( InternalAuthorizationFilter ) per http request. AuthorizationFilterWithFactoryAttribute仍将是单例并创建一次,但我们接近目标以创建每个 http 请求的过滤器 ( InternalAuthorizationFilter )。

You can also take a reference from MSDN .您还可以从MSDN 中获取参考。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM