У меня есть базовый контроллер в моем MVC 5 проекте, который реализует некоторые общие функции. Эта функциональность требует определенных зависимостей. Я использую Unity 3, чтобы внедрить эти реализации в мои контроллеры, шаблон, который работал нормально, пока я не переключил свои контроллеры на наследование с этого базового контроллера. Теперь я бегу в следующем выпуске:Встраивание конструктора базового контроллера в ASP.NET MVC с Unity
public class BaseController : Controller
{
private readonly IService _service;
public BaseController(IService service)
{
_service = service;
}
}
public class ChildController : BaseController
{
private readonly IDifferentService _differentService;
public ChildController(IDifferentService differentService)
{
_differentService = differentService;
}
}
Это, по понятным причинам бросает ошибку в 'BaseController' does not contain a constructor that takes 0 arguments
. Unity не разрешает построение BaseController, поэтому он не может вставлять в него зависимостей. Я вижу два очевидных пути решения этой проблемы:
1.) Явный вызвать BaseController CTOR и имеют каждый ChildController т е р инъекционных зависимости в BaseController в
public class ChildController : BaseController
{
private readonly IDifferentService _differentService;
public ChildController(IDifferentService differentService,
IService baseService)
: base(baseService)
{
_differentService = differentService;
}
}
мне не нравится этот подход по нескольким причинам : один из них, потому что ChildControllers не используют дополнительные зависимости (поэтому он вызывает размытие конструктора в дочерних контроллерах без причины), и что более важно, если я когда-либо изменяю подпись конструктора базового контроллера, я должен изменить конструкторские подписи каждого дочернего контроллера.
2.) Реализовать зависимости в BaseController с помощью инъекции собственности
public class BaseController : Controller
{
[Dependency]
public IService Service { get; set; }
public BaseController() { }
}
Мне нравится этот подход лучше - я не использую любого из зависимостей в конструкторе коде BaseController - но она делает инъекции зависимостей стратегия кода непоследовательная, что тоже не идеально.
Существует, вероятно, еще лучший подход, который включает в себя некоторую функцию разрешения зависимостей BaseController, которая вызывает контейнер Unity для сортировки подписи метода ctor, но прежде чем я начну писать что-либо слишком, я задавался вопросом, разрешил ли кто-либо эта проблема раньше? Я нашел несколько решений, плавающих в Интернете, но они были обходными решениями, такими как Service Locator, которые я не хочу использовать.
Спасибо!
Вы правы! Я добавил базовый контроллер в качестве решения, требующего совместной работы без полного учета последствий OO. Я думаю, что я сделаю немного рефакторинг, чтобы гарантировать, что базовые зависимости хороши и аккуратны, и передавайте их через дочерние конструкторы, как вы предлагаете. Спасибо Эрик! – NWard
Возможно, это правильный ответ здесь, но, к сожалению, хотя я могу заключить инициализацию кода в базовом классе, каждый производный класс должен реализовать правильный конструктор. Я должен помнить, чтобы вводить тот же самый конструктор для каждого производного класса. И любое изменение данных, которые я передаю конструктору, требует изменения каждого класса, который вытекает из него. Было бы гораздо лучше иметь возможность поддерживать это только из базового класса. –
@JonathanWood - этот аргумент не является особенно убедительным, поскольку конструкторы существуют по какой-то причине ... Вы хотите инициализировать объект конкретными данными. Если вы «забыли» включить правый конструктор, то задача, которую вы хотите выполнить, не будет работать, потому что не будет конструктора, который вам нужен, и вы быстро заметите свою ошибку. Это похоже на то, что вы должны «помнить», чтобы добавить свойства, которые вам нужны для класса ... вы не получите очень далеко, если не помните. –