使用 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<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)。这与 博客文章。我缺少哪一块拼图?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我的做法略有不同。我会:
安装 unity.mvc3 nuget 包
调用 bootstrapped.initialise(),如 txt 文档中所述,包添加到项目
在初始化中定义您的 IMetadataService 映射到您的具体类型
将 IMetadataService 添加到您的构造函数
您的实现与您引用的文章之间的区别是您使用 Func,我不确定这是否会增加一个不同的问题在这里混合。我必须想象它确实如此,因为上面的方法(没有 Func)对我来说效果很好。
编辑:
Brad Wilson 的代码在这里对我来说效果很好:
http://bradwilson.typepad.com/blog/2010/07/service- location-pt4-filters.html
适用部分(请参阅上面的链接)
Global.asax.cs
过滤器本身:
和 UnityFilterAttributeFilterProvider.cs
I would do this slightly differently. I would:
install the unity.mvc3 nuget package
call the bootstrapped.initialise() as mentioned in the txt doc the package adds to the project
define your IMetadataService mapping in the initialize to your Concrete type
add IMetadataService to your constructor
The difference between your implementation and the article you references is you use Func, which Im not sure if that adds a different problem to the mix here. I have to imagine it does as the above method (without Func) works fine for me.
Edit:
Brad Wilson's code worked just fine for me here:
http://bradwilson.typepad.com/blog/2010/07/service-location-pt4-filters.html
Applicable parts (please see the link above)
Global.asax.cs
The filter itself:
and UnityFilterAttributeFilterProvider.cs