ASP.NET MVC 3依赖注入 - 控制器,视图和动作过滤器

时间:2012-05-30 09:14:01

标签: asp.net-mvc-3 dependency-injection unity-container

我正在尝试使用Microsoft Unity在ASP.NET MVC 3应用程序中使用依赖注入工作。首先,我实现了自己的IDependencyResolver并在我的Global.asax文件中激活它,如下所示:

DependencyResolver.SetResolver(new UnityDependencyResolver(container));

我发现我不需要做任何其他事情来控制器注入(通过构造函数和[Dependency]属性)来工作。使用默认视图引擎,我还发现我可以使[Dependency]属性在标准视图中工作,但不能在布局视图中工作。是否有可能使布局视图也适用?

但是我实现了自己的视图引擎,该引擎继承自VirtualPathProviderViewEngine,它覆盖CreateView / CreatePartialView方法并返回我自己的自定义视图(实现IView)。请参阅下面自定义视图的Render方法:

public void Render(ViewContext viewContext, TextWriter writer) {
    var webViewPage = DependencyResolver.Current.GetService(_type) as WebViewPage;
    //var webViewPage = Activator.CreateInstance(_type) as WebViewPage;

    if (webViewPage == null)
        throw new InvalidOperationException("Invalid view type");

    webViewPage.VirtualPath = _virtualPath;
    webViewPage.ViewContext = viewContext;
    webViewPage.ViewData = viewContext.ViewData;
    webViewPage.InitHelpers();

    WebPageRenderingBase startPage = null;

    if (_runViewStartPages)
        startPage = StartPage.GetStartPage(webViewPage, "_ViewStart", _viewStartFileExtensions);

    var pageContext = new WebPageContext(viewContext.HttpContext, webViewPage, null);
    webViewPage.ExecutePageHierarchy(pageContext, writer, startPage);
}

使用注释掉的行我在视图中完全丢失了依赖注入,所以我将其更改为上面的行,这对于标准视图再次正常工作,但不适用于布局视图。如果您能告诉我如何修改上述内容以适应布局视图,我会很感激吗?

最后,我正在努力让动作过滤器注入工作。我发现了两种不同的情况:

  1. 通过属性将过滤器应用于操作。

  2. 将其定义为全局过滤器,例如:

    GlobalFilters.Filters.Add(new TestAttribute());

  3. 似乎都没有使用依赖项解析器。因此我需要做一些额外的工作。如果有更好的方法,请纠正我。为了启用第一个方案,我执行了以下操作:

    public class UnityFilterAttributeFilterProvider : FilterAttributeFilterProvider {
        private IUnityContainer _container;
    
        protected override IEnumerable<FilterAttribute> 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<FilterAttribute> GetActionAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor) {
            var attributes = base.GetActionAttributes(controllerContext, actionDescriptor);
    
            foreach (var attribute in attributes) {
                _container.BuildUp(attribute.GetType(), attribute);
            }
    
            return attributes;
        }
    }
    

    然后在我的Global.asax文件中定义它,如下所示:

    FilterProviders.Providers.Remove(FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider));
    FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));
    

    这很好但我想知道这是否是正确的方法呢?为了解决第二种情况,我只是将我定义全局过滤器的位置更改为以下内容:

    GlobalFilters.Filters.Add(DependencyResolver.Current.GetService<TestAttribute>());
    

    这再次起作用,但这是正确的方法吗?

    我很感激帮助。感谢

0 个答案:

没有答案