跟进Authorization Filter Dependency Injection with ASP.New MVC 4 Web Api。有没有办法在所有控制器类上全局设置的过滤器上使用依赖注入:
config.Filters.Add(new WebApplicationApiAuthorizeAttribute());
GetFilters
中的ActionDescriptorFilterProvider
方法似乎只适用于方法级过滤器。
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);
}
}
}
答案 0 :(得分:4)
如果您希望注入这些全局过滤器,则必须从容器中解析它们并将它们添加到过滤器集合中:
GlobalFilters.Filters.Add(container.Resolve<MyFilter>());
或做类似的事情:
var filter = WebApplicationApiAuthorizeAttribute();
container.BuildUp(filter.Gettype(), filter);
GlobalFilters.Filters.Add(filter);
但是关于使用全局过滤器的一个重要警告。全局过滤器是......全局的。或者在IoC术语中:它们是单身人士。这意味着它的所有依赖关系也将有效地成为单例,这可能会导致各种并发错误,因为它们在应用程序期间不会存在。
因此,只有当所有过滤器的直接和间接依赖关系都是单例时,才应该这样做,如果你能做到这一点,这很好,但通常情况并非如此。所以另一个选择是创建一个允许动态解析实例的代理:
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; } }
}
此代理可以在全局过滤器集合中作为单例注入,如下所示:
GlobalFilters.Filters.Add(
container.Resolve<UnityActionFilterProxy<MyFilter>>());
全局过滤器并不是Web API中唯一一个设计有点......臭的地方。请查看有关DelegatingHandlers的this related question。