我正在尝试使用 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);
}
通过注释掉的行,我完全失去了视图中的依赖注入,因此我将其更改为上面的行,该行再次适用于标准视图,但不适用于布局视图。如果您能向我展示如何修改上述内容以适用于布局视图,我将不胜感激?
最后,我试图让动作过滤器注入也正常工作。我发现了两种不同的情况:
通过属性将过滤器应用到操作。
-
将其定义为全局过滤器,例如:
GlobalFilters.Filters.Add(new TestAttribute());
两者似乎都没有使用依赖解析器。因此我需要做一些额外的工作。如果有更好的方法请指正。为了启用第一个场景,我执行了以下操作:
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>());
现在这又可以了,但是这是正确的方法吗?
我将不胜感激的帮助。谢谢