实现IActionModelConvention和IFilterFactory的Asp.net Core自定义过滤器

时间:2018-11-28 18:13:09

标签: c# asp.net-core asp.net-core-mvc asp.net-core-2.1 custom-action-filter

我需要创建一个实现IActionModelConventionIFilterFactory的自定义操作过滤器。

我使用IActionModelConvention同时设置多条路由,并且我使用IFilterFactory注入一些我需要使用的服务。

问题是,在Apply()的{​​{1}}方法之前调用了IActionModelConvention的{​​{1}}方法,我需要注入的服务将在CreateInstance()中可用。

我的问题是在调用IFilterFactory方法之前如何注入服务?而且我还更喜欢使用Apply()来注入服务,因为这不会迫使我用Apply()IFilterFactory属性来包装实际属性。

这是我的代码:

[ServiceFilter]

1 个答案:

答案 0 :(得分:1)

您的IActionModelConvention实现在启动时将只运行一次。 Apply将为每个操作调用一次。为了在ISomeService函数内部使用Apply,可以将其作为构造函数参数传递。您的Contains2RoutesAttribute类不必是IFilterFactory的属性或实现,因为您已经在注释中确认它不参与filter pipeline。这是一个代码示例,在这里我还重命名了该类以更好地表示其正在执行的操作(它不再是属性):

public class Contains2RoutesConvention : IActionModelConvention
{
    private readonly ISomeService someService;

    public Contains2RoutesConvention(ISomeService someService)
    {
        this.someService = someService;
    }

    public void Apply(ActionModel actionModel)
    {
        someService.DoSomething();

        ...
    }
}

您可以使用以下方法在Startup.ConfigureServices中注册此约定:

services.AddMvc(options =>
{
    options.Conventions.Add(new Contains2RoutesConvention(new SomeService()));
});

在这里变得更加有趣。您不能在convention中使用依赖项注入,因此在此示例中,我在构造SomeService时内联创建了Contains2RoutesConvention的实例。如果您希望该实例成为可在应用程序中其他位置使用的单例,则可以在ConfigureServices中进行如下操作:

var someService = new SomeService();

services.AddMvc(options =>
{
    options.Conventions.Add(new Contains2RoutesConvention(someService));
});

services.AddSingleton<ISomeService>(someService);

当然,这取决于SomeService是否具有自己的依赖关系,但是如果存在依赖关系,则它们将无法从DI容器中解决,因为它在管道中为时过早。