Задать вопрос

[DI] Resolve типа внутри метода контроллера (ASP.MVC). Как реализовать?

Доброго времени суток.
В моем проекте есть куча разных репозиториев и их интерфейсов. В методе контроллера хотелось бы получать реализацию конкретного репозитория следующим образом:
public ActionResult SomeMethod(){
   var someRepo = ObjectFactory.Resolve<ISomeRepository>();
   return Content(someRepo.SomeAction());
}

В интернете много информации о различных DI контейнерах (Ninject, Unity ...). Проблема в том, что они резолвят параметры конструктора. Я думал использовать Unity таким образом, как писал выше, но наткнулся на эту ссылку unity.codeplex.com/discussions/640841, где говорится, что так использовать Unity нехорошо.
Существуют ли какие-нибудь готовые решения, позволяющие резолвить типы внутри метода контроллера (желательно с возможностью настройки через XML, как в Unity)?
  • Вопрос задан
  • 226 просмотров
Подписаться 3 Оценить 5 комментариев
Пригласить эксперта
Ответы на вопрос 2
@Free_ze
Пишу комментарии в комментарии, а не в ответы
DependencyResolver.Current.GetService(typeof(IMyService))
Ответ написан
Valeriy1991
@Valeriy1991
Разработчик .NET C# (ASP.NET MVC) в Alfa-B, Moscow
Существуют ли какие-нибудь готовые решения, позволяющие резолвить типы внутри метода контроллера (желательно с возможностью настройки через XML, как в Unity)?

Добрый день!
Если Вы пытаетесь резолвить что-то из IoC-контейнера в методе действия, значит, Вы идете по не совсем правильному пути (т.к. резолвить напрямую из контейнера приводит к значительным утечкам памяти из-за того, что GC не может их очистить, т.к. они "используются" самим IoC-контейнером). Что мешает Вам передавать Ваш ISomeRepository в конструктор контроллера и записывать его в private field?

Я бы делал так, как предложил Free_ze в комментариях к Вашему вопросу:
  1. Пишем фабрику контроллеров (или подключаем готовую, если она есть в комплекте с IoC-контейнером)
  2. Вставляем интерфейсы в конструкторы контроллеров


Контроллер будет выглядеть в этом случае так:
private readonly ISomeRepository _someRepo;
public MyController(ISomeRepository someRepo)
{
    if(someRepo == null)
        throw new ArgumentNullException(nameof(someRepo));
    _someRepo = someRepo;
}


Дальше используем _someRepo как душе будет угодно. Такой подход более правильный с точки зрения разрешения зависимостей. Про IoC-контейнер, по сути, должен знать только тот, кто его конфигурирует.

P.S. Бонус: если у Вас много репозиториев и интерфейсов для них, значит, настала пора рефакторинга. Смотрите в сторону GenericRepository + UnitOfWork.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы