目前,我有一个自定义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<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);
}
以下是正在构建的一个ActionFilter的示例:
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上的公共属性从未注入任何内容,它在执行时仍为null!我不明白为什么我的过滤器没有被容器正确构建。注入的类型已正确注册,如下所示:
container.RegisterInstance(new ChannelFactory<IMetadataService>(
new BasicHttpBinding(),
new EndpointAddress("http://example.com/ABSApplication/MetadataService.svc")));
container.RegisterInstance<Func<IMetadataService>>(
() => container.Resolve<ChannelFactory<IMetadataService>>().CreateChannel());
并且还在应用程序的其他地方注入(尽管不是通过.Buildup)。这与blog post所遵循的流程几乎相同。我错过了哪一块拼图?
答案 0 :(得分:8)
我会稍微改变一下。我会:
安装unity.mvc3 nuget包
调用bootstrap.initialise(),如包中添加到项目的txt文档中所述
在初始化为Concrete类型
将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;
}
}