ServiceFilter和TypeFilter - 注入这些过滤器有什么区别?

MrC*_*udz 10 c# asp.net-core-mvc asp.net-core

ServiceFilter我们必须在Startup.cs中注册.TypeFilter是由Microsoft.Extensions.DependencyInjection.ObjectFactory注入的,我们不需要注册那个过滤器.

那么当我们应该使用ServiceFilter和TypeFilter时?

Yaw*_*aza 8

根据Pro ASP.NET Core MVC 2的书。第19章:过滤器,第615页

使用TypeFilter属性时,将为每个请求创建过滤器类的新实例。这与将过滤器直接用作属性的行为相同,不同之处在于TypeFilter属性允许过滤器类声明通过服务提供者解析的依赖项。ServiceFilter属性更进一步,并使用服务提供者来创建过滤器对象。这也允许将过滤器对象置于生命周期管理下。

差异 由于会ServiceFilter使用ServiceProvider来解析相关过滤器的实例,因此您可以控制在启动类中注册的过滤器的生命周期:

services.AddSingleton<TimeFilter>();
Run Code Online (Sandbox Code Playgroud)

从上面的代码行中,TimeFilter将仅为MVC应用程序生命周期创建一次(不适用于每个http请求生命周期或当客户要求时),它将为所有http请求服务,TypeFilter因为无法使用,因此无法使用您可以指示MVC框架何时实例化和配置在下使用的过滤器TypeFilter

如果将过滤器注册为,Singleton则仅创建该过滤器的一个实例,这意味着CLR的工作量减少,这与TypeFilter为每个http请求创建过滤器类的新实例不同。

用法 假设您TypeFilter对两个操作方法应用了一个方法,对于每个HTTP请求,TypeFilter将创建一个新实例,将调用该构造函数并注入依赖项(您可以使用来控制依赖项的生命周期Service Provider)。与此相反,ServiceFilter你决定,如果它SingletonScopedTransient。如果是,Singleton则仅为所有请求创建一个实例。

要记住的关键

我们要使用ServiceFilter和来管理过滤器类型的生命周期Service Provider。如果过滤器具有依赖项,则我们已经Service Provider像往常一样使用来进行管理。


Set*_*Set 7

好的,所以文档:

  • A ServiceFilter从DI检索过滤器的实例.使用ServiceFilter而不注册过滤器类型会导致异常.

  • TypeFilterAttributeServiceFilterAttribute(并且还实现IFilterFactory)非常相似,但它的类型不能直接从DI容器中解析.相反,它通过使用实例化类型Microsoft.Extensions.DependencyInjection.ObjectFactory.

由于存在这种差异,使用TypeFilterAttribute 不需要首先向容器注册的类型(但它们仍将通过容器实现其依赖关系).

  • 我知道 - 但我仍然不知道什么时候应该使用 ServiceFilter 以及什么时候应该使用 Typefilter。 (3认同)
  • 那么究竟什么是“Microsoft.Extensions.DependencyInjection.ObjectFactory”?如果您不将其注册到容器中,这将如何工作? (2认同)

小智 6

ServiceFilter和TypeFilter都是使用依赖项注入构造的。

根据对TypeFilter使用实例化Microsoft.Extensions.DependencyInjection.ObjectFactory,最终让你自己提供构造函数的参数(你可以看到一个参数的构造函数中的参数)。它还可以解决您不提供的服务。

因此,您可以执行以下操作:

public class AttachMetadataAttribute : Attribute, IAsyncActionFilter
{
    public AttachMetadataAttribute(SomeType someValue, ISomeService service)
        {
        }
}
Run Code Online (Sandbox Code Playgroud)

您可以这样使用:

[TypeFilter(typeof(AttachMetadataAttribute),
    IsReusable = true,
    Order = 10,
    Arguments = new object[] { someValue})]
Run Code Online (Sandbox Code Playgroud)

因此,这里第一个参数(someValue)由您提供,服务由容器注入。

注意:注意IsReusable。如果将其设置为true,则注入的服务仅创建一次。