Вызов конструктора базового класса в явном виде - единственный способ сделать это, используя внедрение конструктора в C #. Похоже, вы должны удалить конструкторы без параметров из BaseController
и PublicController
, так как они никогда не должны вызываться, когда доступен регистратор.
Проблема внедрения зависимостей в базовый контроллер является обычной для ASP.NET MVC и IoC. Есть несколько вариантов / школ мысли.
1.) Используйте совокупные услуги. Чтобы сохранить конструкторы производных классов простыми, создайте единый сервис, который предоставляет или делегирует все различные сервисы, необходимые базовому контроллеру (например, IBaseControllerDependencies
или аналогичный). Затем передайте этот единственный сервис BaseController
, как вы это делаете с ILogger
здесь.
Существуют различные плюсы и минусы в зависимости от вашего приложения и количества используемых вами базовых классов. Чтобы узнать больше об этом, обратитесь к Google за «Агрегатными услугами Autofac».
2.) Используйте свойство инъекции. Сделайте свойство ILogger
вашего базового класса общедоступным и настройте контейнер, используя:
builder.RegisterControllers().PropertiesAutowired();
Внедрение свойств на самом деле не является предпочтительным методом в Autofac. Роль конструктора заключается в в принятии зависимостей, в то время как свойства для записи часто воспринимаются как запах кода, поэтому Autofac действительно не оптимизирует для этого случая. Одним из недостатков является то, что свойства записи, которые не следует вводить , часто ошибочно приводят к странным последствиям.
3.) Реорганизовать функциональность базового контроллера в различные фильтры действий. Autofac может внедрить фильтры действий в конвейер вызова действий MVC. Таким образом, фильтры могут принимать зависимости, которые были от базового класса, и те же проблемы могут применяться сквозным образом. Подробнее об этом в Интернете, ExtensibleActionInvoker
и .InjectActionInvoker()
указывают на информацию, которая вам понадобится. Не всегда возможно со всеми проблемами.
4, также ответ на ваш второй вопрос.) Разрешите зависимости базового контроллера, используя расположение службы из DependencyResolver.Current
.
var logger = DependencyResolver.Current.GetService<ILogger>();
Причина, по которой это не поощряется, состоит в том, что это усложняет понимание получающегося приложения, потому что больше невозможно увидеть, от каких сервисов зависит компонент, просматривая в одном месте (конструктор). Чтобы определить, что необходимо настроить в контейнере, прежде чем можно будет использовать конкретный компонент, нужно посмотреть на всю кодовую базу компонента, чтобы найти вызовы GetService()
. Заметное препятствие при юнит-тестировании.
Надеюсь, это поможет, немного мозгов, я знаю :) Другие, возможно, могут добавить еще несколько идей к ним.