我有一个HandleErrorAttribute
扩展的习惯FilterAttribute
。
如何让 Unity 在注入控制器依赖项本身的同时将依赖项注入此属性?
我有一个HandleErrorAttribute
扩展的习惯FilterAttribute
。
如何让 Unity 在注入控制器依赖项本身的同时将依赖项注入此属性?
好的,想通了。
大多数情况下,我从他指出的博客文章中使用了 Ben 在上面的解决方案。
问题是 Unity 的行为有点不同。
您不能直接在过滤器上注入依赖项,因为它们分别属于 IActionFilter 和 IExceptionFilter 类型。这让我相信它们是只读的,但事实并非如此。只是 Unity 需要知道显式类型才能注入。
因此,在文章提供的重写方法中,Unity 用户需要查询过滤器的相关类型,然后构建它们。
public UnityActionInvoker(IUnityContainer container, IList<Type> typesToInject)
{
_container = container;
_typesToInject = typesToInject;
}
然后在覆盖的方法中,执行以下操作:
var needsInjection = filters.Where(filter => typesToInject.Contains(filter.GetType()));
有点混乱,但它只需要完成一次,并且按照 Ben 的建议保持一切解耦。
另一个问题是您不能在 foreach 循环中调用 _container.BuildUp(filter) ,因为过滤器在该上下文中是只读的。
你有两个选择
第一种选择是编写一个自定义的 ActionInvoker,这并不像听起来那么难。看看这篇博文。它专门处理 NInject,但 Unity 支持属性注入,因此您可以修改示例以使用 Unity。
这是与您的 IoC 容器耦合的选项,不推荐使用。
public class MyFilter
{
IMyService MyService {get; set;}
MyFilter() : MyFilter(MyUnityContainer.Resolve<IMyService>())
{ }
MyFilter(IMyService service)
{
MyService = service;
}
}
我也遇到了这个问题,现在有一个可行的解决方案。它与上述解决方案类似,但有一些细微差别,并且添加了完整的 Unity 代码。
首先,出于上述原因,我将使用属性注入,并且如上所述,我将使用 Unity 上的 BuildUp 方法将属性注入到已创建的过滤器中。
为此,我让我的所有控制器都继承自一个新的自定义基类。在该基类上,我重写了 CreateActionInvoker 方法以设置我自己的自定义 ActionInvoker。
Protected Overrides Function CreateActionInvoker() As System.Web.Mvc.IActionInvoker
Return CustomActionInvoker
End Function
然后在我的 CustomActionInvoker 中,我重写了 GetFilters 方法。
Protected Overrides Function GetFilters(ByVal controllerContext As ControllerContext, ByVal actionDescriptor As ActionDescriptor) As FilterInfo
Dim info = MyBase.GetFilters(controllerContext, actionDescriptor)
For Each MyAuthorizationFilter In info.AuthorizationFilters
MvcApplication.Container.BuildUp(MyAuthorizationFilter.GetType, MyAuthorizationFilter)
Next
For Each MyActionFilter In info.ActionFilters
MvcApplication.Container.BuildUp(MyActionFilter.GetType, MyActionFilter)
Next
For Each MyResultFilter In info.ResultFilters
MvcApplication.Container.BuildUp(MyResultFilter.GetType, MyResultFilter)
Next
For Each MyExceptionFilter In info.ExceptionFilters
MvcApplication.Container.BuildUp(MyExceptionFilter.GetType, MyExceptionFilter)
Next
Return info
End Function
与上面所说的相反,我没有发现在 For Each 循环中进行构建会导致任何问题。我还克服了最初的问题,即只通过接口引用对象,方法是使用 BuildUp 方法的其他重载之一,该方法采用 System.Type 以及现有对象。
完成以上所有操作后,我现在可以将依赖项直接注入我的过滤器。
任何意见和想法都非常感谢。
干杯迈克