使用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)。 这与博客文章所遵循的流程几乎相同。 我错过了哪一块拼图?
我会稍微改变一下。 我会:
-
安装unity.mvc3 nuget包
-
调用bootstrapped.initialise(),如包中添加到项目中的txt doc中所述
-
在初始化为Concrete类型时定义IMetadataService映射
-
将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; } }