Я пытаюсь заставить инъекцию зависимостей работать в приложении ASP.NET MVC 3 с использованием Microsoft Unity. Сначала я реализовал свой собственный IDependencyResolver и активировал его в своем файле Global.asax следующим образом:
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
Я обнаружил, что мне не нужно ничего делать, чтобы заставить работать внедрение контроллера (как через конструктор, так и через атрибут [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(новый 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>());
Теперь это снова работает, но правильно ли это?
Буду признателен за помощь. Спасибо