MVC / Unity - 如何将依赖项注入自定义FilterAttributes?

时间:2009-06-23 22:31:05

标签: asp.net-mvc unity-container filterattribute

我有一个HandleErrorAttribute的自定义FilterAttribute

如何在注入控制器的依赖项本身的同时将Unity注入依赖项注入此属性?

3 个答案:

答案 0 :(得分:2)

好的,想通了。

大多数情况下,我在他指出的博客文章中使用了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),因为过滤器在该上下文中是只读的。

答案 1 :(得分:1)

您有两个选择

第一个选项是编写一个自定义的ActionInvoker,它听起来并不像听起来那么难。看看这个blog post。它专门处理NInject,但Unity支持属性注入,因此您可以修改示例以使用Unity。

这是耦合IoC容器的选项,不推荐使用。

public class MyFilter 
{ 
  IMyService MyService {get; set;}

  MyFilter() : MyFilter(MyUnityContainer.Resolve<IMyService>())
  { }

  MyFilter(IMyService service)
  {
    MyService = service;
  }
}

答案 2 :(得分:1)

我也遇到过这个问题,现在有一个有效的解决方案。它类似于上面描述的解决方案,但有一些细微的差别,并且还添加了完整的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以及现有对象。

完成上述所有操作后,我现在可以将依赖项直接注入到我的过滤器中。

非常感谢任何评论和想法。

干杯迈克