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

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

在global.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 filters, ActionDescriptor actionDescriptor, IDictionary parameters) { var builtUpFilters = new List(); foreach (IActionFilter actionFilter in filters) { builtUpFilters.Add(_container.BuildUp(actionFilter)); } return base.InvokeActionMethodWithFilters(controllerContext, builtUpFilters, actionDescriptor, parameters); } 

以下是正在构建的ActionFilters之一的示例:

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

问题是我的自定义ActionFilterAttribute上的公共属性从未注入任何内容,它在执行时仍为null! 我不明白为什么我的filter没有被容器正确构建。 注入的类型已正确注册,如下所示:

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

并且还在应用程序的其他地方注入(虽然不是通过.Buildup)。 这与博客文章所遵循的流程几乎相同。 我错过了哪一块拼图?

我会稍微改变一下。 我会:

  1. 安装unity.mvc3 nuget包

  2. 调用bootstrapped.initialise(),如包中添加到项目中的txt doc中所述

  3. 在初始化为Concrete类型时定义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); // ... }
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); // ... } 

filter本身:

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(" 

filter说2 + 3是{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; } }
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; } }