使用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。mvc3 nuget包
-
调用bootstrapping . initialize(),就像包添加到项目的txt文档中提到的那样
-
在初始化中定义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);
// ...
}
之前过滤器本身:
<>之前
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;
}
}