实现IActionModelConvention和IFilterFactory的Asp.net Core自定义过滤器 [英] Asp.net Core custom filter implementing IActionModelConvention and IFilterFactory

查看:271
本文介绍了实现IActionModelConvention和IFilterFactory的Asp.net Core自定义过滤器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要创建同时实现IActionModelConventionIFilterFactory的自定义操作过滤器.

I need to create a custom action filter that implements both IActionModelConvention and IFilterFactory.

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

I use IActionModelConvention for setting several routes at the same time, and I use IFilterFactory to inject some services I need to use.

问题是,在IFilterFactoryCreateInstance()方法之前调用了IActionModelConventionApply()方法,并且我需要注入的服务在Apply().

The problem is that the Apply() method from the IActionModelConvention is being called before the CreateInstance() method from the IFilterFactory, and I need the injected services to be available in the Apply().

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

My question is how do I inject the services before the Apply() method is being called? and I also prefer to use IFilterFactory to inject services because it doesn't force me to wrap the actual attribute with the [ServiceFilter] or [TypeFilter] attributes.

这是我的代码:

public class Contains2RoutesAttribute : Attribute, IActionModelConvention, IFilterFactory
{
    public ISomeService SomeService{ get; set; }

    public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
    {
        ISomeService someService = serviceProvider.GetService<ISomeService>();
        return new Contains2RoutesAttribute() { SomeService = someService };
    }

    public void Apply(ActionModel action)
    {
        // Here I need to use the service injected:
        this.SomeService.DoSomething(); // ERROR: The service here is null.

        action.Selectors.Clear();

        // Adding route 1:
        action.Selectors.Add(new SelectorModel
        {
            AttributeRouteModel = new AttributeRouteModel { Template = "~/index1" }
        });

        // Adding route 2:
        action.Selectors.Add(new SelectorModel
        {
            AttributeRouteModel = new AttributeRouteModel { Template = "~/index2" }
        });
    }
}

推荐答案

您的IActionModelConvention实现在启动时仅运行一次. Apply将为每个动作调用一次.要在Apply函数内部使用ISomeService,请将其作为构造函数参数传递.您的Contains2RoutesAttribute类不必是IFilterFactory的属性或实现,正如您在注释中确认的那样,它不参与

Your IActionModelConvention implementation will run only once, at startup. Apply will be called once for each action. To use ISomeService inside of the Apply function, pass it through as a constructor argument. Your Contains2RoutesAttribute class need not be an attribute or an implementation of IFilterFactory, as you've confirmed in the comments that it does not participate in the filter pipeline. Here's a code example, where I've also renamed the class to better represent what it's doing (it's no longer an attribute):

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()));
});

在这里变得更加有趣.您不能将依赖项注入与

This is where it gets a bit more interesting. You can't use dependency injection with a convention, so in this example, I've created an instance of SomeService inline when constructing Contains2RoutesConvention. If you want this instance to be a singleton that can be used elsewhere in your application, you can do something like this in ConfigureServices:

var someService = new SomeService();

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

services.AddSingleton<ISomeService>(someService);

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

Of course, this depends on whether or not SomeService has dependencies of its own, but if it does, they would not be resolvable from the DI container as it's too early in the pipeline.

这篇关于实现IActionModelConvention和IFilterFactory的Asp.net Core自定义过滤器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆