使用Unity将依赖项注入到自定义ActionFilter中

本文关键字:自定义 ActionFilter 注入 Unity 依赖 使用 | 更新日期: 2023-09-27 18:15:17

目前,我有一个自定义的ControllerFactory,我注入我的Unity容器:

在全球。asax Application_Start ():

var container = InitContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
var factory = new UnityControllerFactory(container);
ControllerBuilder.Current.SetControllerFactory(factory);

在控制器工厂中,我设置控制器使用自定义ActionInvoker,如下所示:

protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
    var controller = base.GetControllerInstance(requestContext, controllerType) as Controller;
    if (controller != null)
        controller.ActionInvoker = new UnityActionInvoker(_container);
    return controller;
}

最后在我的自定义ActionInvoker中,我尝试使用ActionInvokers容器来构建被调用的动作:

protected override ActionExecutedContext InvokeActionMethodWithFilters(
        ControllerContext controllerContext,
        IList<IActionFilter> filters,
        ActionDescriptor actionDescriptor,
        IDictionary<string, object> parameters)
{
    var builtUpFilters = new List<IActionFilter>();
    foreach (IActionFilter actionFilter in filters)
    {
        builtUpFilters.Add(_container.BuildUp<IActionFilter>(actionFilter));
    }
    return base.InvokeActionMethodWithFilters(controllerContext, builtUpFilters, actionDescriptor, parameters);
}

下面是一个正在构建的ActionFilters的例子:

public class PopulatRolesAttribute : ActionFilterAttribute, IActionFilter
{
    private const string RolesKey = "roles";
    [Dependency]
    public Func<IMetadataService> Service { get; set; }
    public PopulatRolesAttribute()
    {
    }
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.Controller.ViewData[RolesKey] == null)
        {
            filterContext.Controller.ViewData[RolesKey] = Service().GetRoles();
        }
    }
}

问题是,我的自定义ActionFilterAttribute上的公共属性从未注入任何东西,它在执行时仍然为空!我看不出为什么我的过滤器没有被容器正确地建立。被注入的类型被正确注册,如下所示:

container.RegisterInstance(new ChannelFactory<IMetadataService>(
    new BasicHttpBinding(),
    new EndpointAddress("http://example.com/ABSApplication/MetadataService.svc")));
container.RegisterInstance<Func<IMetadataService>>(
    () => container.Resolve<ChannelFactory<IMetadataService>>().CreateChannel());

和也被注入到应用程序的其他地方(尽管不是通过.积聚)。这与本文所遵循的过程基本相同。我错过了哪一块拼图?

使用Unity将依赖项注入到自定义ActionFilter中

我的做法略有不同。我想:

  1. 安装unity。mvc3 nuget包

  2. 调用bootstrapping . initialize(),就像包添加到项目的txt文档中提到的那样

  3. 在初始化中定义IMetadataService映射到你的具体类型

  4. 在构造函数中添加IMetadataService

你的实现和你引用的文章之间的区别是你使用了Func,我不确定这是否给这里的混合添加了不同的问题。我不得不想象上面的方法(没有Func)对我来说工作得很好。

编辑:Brad Wilson的代码在这里工作得很好:http://bradwilson.typepad.com/blog/2010/07/service-location-pt4-filters.html

适用部件(请参见上面的链接)

Global.asax.cs

<>之前 protected void Application_Start() { // ... var oldProvider = FilterProviders.Providers.Single( f => f is FilterAttributeFilterProvider ); FilterProviders.Providers.Remove(oldProvider); var container = new UnityContainer(); var provider = new UnityFilterAttributeFilterProvider(container); FilterProviders.Providers.Add(provider); // ... } 之前

过滤器本身:

<>之前 using System; using System.Web.Mvc; using Microsoft.Practices.Unity; public class InjectedFilterAttribute : ActionFilterAttribute { [Dependency] public IMathService MathService { get; set; } public override void OnResultExecuted(ResultExecutedContext filterContext) { filterContext.HttpContext.Response.Write( String.Format("

The filter says 2 + 3 is {0}.

", MathService.Add(2, 3)) ); } }
之前

和UnityFilterAttributeFilterProvider.cs

<>之前 using System.Collections.Generic; using System.Web.Mvc; using Microsoft.Practices.Unity; public class UnityFilterAttributeFilterProvider : FilterAttributeFilterProvider { private IUnityContainer _container; public UnityFilterAttributeFilterProvider(IUnityContainer container) { _container = container; } protected override IEnumerable GetControllerAttributes( ControllerContext controllerContext, ActionDescriptor actionDescriptor) { var attributes = base.GetControllerAttributes(controllerContext, actionDescriptor); foreach (var attribute in attributes) { _container.BuildUp(attribute.GetType(), attribute); } return attributes; } protected override IEnumerable GetActionAttributes( ControllerContext controllerContext, ActionDescriptor actionDescriptor) { var attributes = base.GetActionAttributes(controllerContext, actionDescriptor); foreach (var attribute in attributes) { _container.BuildUp(attribute.GetType(), attribute); } return attributes; } }