【问题标题】:ServiceFilter and TypeFilter - what is the difference in injection those filters?ServiceFilter 和 TypeFilter - 注入这些过滤器有什么区别?
【发布时间】:2017-04-27 12:39:05
【问题描述】:

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

那么我们什么时候应该使用 ServiceFilter 以及什么时候使用 TypeFilter 呢?

【问题讨论】:

  • ASP.NET Core 文档包含过滤器的详细说明。你检查了吗?

标签: c# asp.net-core asp.net-core-mvc


【解决方案1】:

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

当使用 TypeFilter 属性时,过滤器的新实例 为每个请求创建类。这是相同的行为 直接将过滤器作为属性应用,除了 TypeFilter 属性允许过滤器类声明依赖关系 通过服务商解决。服务过滤器属性 更进一步,使用服务提供者创建过滤器 目的。这允许将过滤器对象放置在生命周期下 管理也是如此。

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

services.AddSingleton<TimeFilter>();

从上面的代码行中,TimeFilter 只会为 MVC 应用程序生命周期创建一次(不是为每个 http 请求生命周期或当客户端请求它时),它将为所有 http 请求提供服务,这是不可能的使用TypeFilter,因为您无法指示 MVC 框架何时实例化和处置TypeFilter 下使用的过滤器。

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

用法 假设您在两个操作方法上应用了 TypeFilter,对于每个 HTTP 请求,将创建该 TypeFilter 的新实例,将调用构造函数并注入依赖项(您可以使用控制依赖项的生命周期Service Provider)。相比之下,使用ServiceFilter,您可以决定是Singleton 还是Scoped 还是Transient。如果是Singleton,则只为所有请求创建一个实例。

要记住的关键事项

我们要使用ServiceFilterService Provider 管理过滤器类型的生命周期。如果过滤器有依赖关系,我们已经像往常一样使用Service Provider 来管理它。

【讨论】:

  • 那么,据我了解,ServiceFilter应该在我们不需要提供构造函数参数的时候使用,而TypeFilter应该在我们提供的时候使用?这样,如果我们从不需要提供参数,就可以避免为每个请求不必要地创建 TypeFilter 的新实例?
【解决方案2】:

好的,所以documentation

  • ServiceFilter 从 DI 检索过滤器的实例。在不注册过滤器类型的情况下使用ServiceFilter会导致异常。

  • TypeFilterAttributeServiceFilterAttribute 非常相似(也实现了 IFilterFactory),但其类型不是直接从 DI 容器解析。相反,它使用Microsoft.Extensions.DependencyInjection.ObjectFactory 实例化类型。

由于这种差异,使用TypeFilterAttribute 引用的类型不需要先向容器注册(但它们的依赖关系仍将由容器实现)。

【讨论】:

  • 我知道 - 但我仍然不知道什么时候应该使用 ServiceFilter 以及什么时候应该使用 Typefilter。
  • 那么Microsoft.Extensions.DependencyInjection.ObjectFactory到底是​​什么?如果不向容器注册它如何工作?
【解决方案3】:

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

根据this,TypeFilter 是使用Microsoft.Extensions.DependencyInjection.ObjectFactory 实例化的,这最终允许您自己提供构造函数参数(您可以在其构造函数中看到 Arguments 参数)。它还解决了您不提供的问题。

所以你可以这样做:

public class AttachMetadataAttribute : Attribute, IAsyncActionFilter
{
    public AttachMetadataAttribute(SomeType someValue, ISomeService service)
        {
        }
}

你可以像这样使用它:

[TypeFilter(typeof(AttachMetadataAttribute),
    IsReusable = true,
    Order = 10,
    Arguments = new object[] { someValue})]

所以这里第一个参数(someValue)由你提供,服务由容器注入。

注意:小心 IsReusable。如果设置为 true,则注入的服务只会创建一次。

【讨论】:

    【解决方案4】:

    如果您的过滤器具有需要从容器中解析的依赖项,请使用TypeFilterAttribute。它允许你to perform constructor injection

    【讨论】:

    • 据我所知,他们都允许这样做。区别在于过滤器本身的实例化方式。
    猜你喜欢
    • 1970-01-01
    • 2019-05-01
    • 2019-02-11
    • 2015-04-18
    • 2020-06-28
    • 1970-01-01
    • 1970-01-01
    • 2014-11-06
    相关资源
    最近更新 更多