扩展ActionDescriptorFilterProvider以允许对类级别过滤器进行依赖注入 [英] Extending ActionDescriptorFilterProvider to allow dependency injection of class level filters

查看:199
本文介绍了扩展ActionDescriptorFilterProvider以允许对类级别过滤器进行依赖注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关注授权过滤器依赖项注入ASP.New MVC 4 Web Api 。有没有一种方法可以对在所有控制器类上全局设置的过滤器使用依赖项注入:

Following up on Authorization Filter Dependency Injection with ASP.New MVC 4 Web Api . Is there a way to use dependency injection on filters that are set globally on all controller classes:

config.Filters.Add(new WebApplicationApiAuthorizeAttribute());  

看起来像中的 GetFilters 方法 ActionDescriptorFilterProvider 仅适用于方法级过滤器。

It looks like the GetFilters method in the ActionDescriptorFilterProvider only works on method level filters.

public class UnityWebApiFilterAttributeFilterProvider : ActionDescriptorFilterProvider,
    System.Web.Http.Filters.IFilterProvider
{
private readonly IUnityContainer _container;

public UnityWebApiFilterAttributeFilterProvider(IUnityContainer container)
{
    _container = container;
}

public IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, 
    HttpActionDescriptor actionDescriptor)
{
    var filters = base.GetFilters(configuration, actionDescriptor);

    this.BuildUpAttributes(filters);

    return filters;
}

private void BuildUpAttributes(IEnumerable filterInfo)
{
    foreach (FilterInfo filter in filterInfo)
    {
        object o = _container.BuildUp(filter.GetType(), filter);
    }
}
}


推荐答案

如果要注入这些全局过滤器,则必须从容器中解析它们并将它们添加到过滤器集合中:

If you want these global filters to get injected, you will have to resolve them from the container and add them to the filters collection:

GlobalFilters.Filters.Add(container.Resolve<MyFilter>());

或执行以下操作:

var filter = WebApplicationApiAuthorizeAttribute();
container.BuildUp(filter.Gettype(), filter);
GlobalFilters.Filters.Add(filter);

但是关于使用全局过滤器的一个重大警告。全局过滤器是...全局的。或使用IoC术语:它们是单例。这意味着它的所有依赖关系也将有效地变为单例,这可能会导致各种各样的并发错误,如果它们在应用程序的持续时间内无法生存。

But one big warning about using global filters. Global filters are... global. Or in IoC terminology: they are singletons. This means that all its dependencies will effectively become singletons as well, which might cause all sorts of concurrency bugs when they are not expected to live for the duration of the application.

因此,只有在所有过滤器的直接和间接依赖项都是单例时,才应该这样做,如果可以的话,这样做很好,但通常并非如此。因此,另一种选择是创建一个允许动态解析真实实例的代理:

So you should only do this when all the filter's direct and indirect dependencies are singletons, which is great if you can do this, but often isn't the case. So another option is to create a proxy that allows resolving the real instance on the fly:

public sealed class UnityActionFilterProxy<TActionFilter> : IActionFilter
    where TActionFilter : IActionFilter
{
    private readonly IUnityContainer container;
    public UnityActionFilterProxy(IUnityContainer container) {
        this.container = container;
    }

    public Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext context,
        CancellationToken token, Func<Task<HttpResponseMessage>> continuation) {
        return this.container.Resolve<TActionFilter>().ExecuteActionFilterAsync(
            context, token, continuation);
    }

    public bool AllowMultiple { get { return false; } }
}

此代理可以作为单例注入到全局过滤器集合中,如下所示:

This proxy can be injected as singleton in the global filters collection as follows:

GlobalFilters.Filters.Add(
    container.Resolve<UnityActionFilterProxy<MyFilter>>());

全局过滤器并不是Web API中唯一设计有点地方的地方...臭。看看此相关问题关于DelegatingHandlers。

The global filters isn't the only place in Web API where the design is a bit... smelly. Take a look at this related question about DelegatingHandlers.

这篇关于扩展ActionDescriptorFilterProvider以允许对类级别过滤器进行依赖注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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