Внедрение UnitOfWork в блок Using
Я работал над приложением UnitOfWork / Repository / MVC. Теперь, когда все работает отлично, я хочу отделить UnitOfWork от контроллеров. Один из способов сделать это - ввести зависимость с помощью Ninject (или другого) в конструктор контроллера. Однако это означает, что UnitOfWork будет запущен одновременно с контроллером.
Я хочу использовать мой UnitOfWork с помощью использования блоков следующим образом:
using(var unitOfWork = new IUnitOfWork)
{
return unitOfWork.GetRepository<IEmployeesRepository>().GetAllEmployees();
}
Очевидно, вы не можете создать экземпляр интерфейса, у вас есть экземпляр реализации, который внедряется с помощью инжектора зависимостей, но как я могу внедрить его в предложении using?
Я видел инъекцию свойств и метод инъекций, но я не уверен, как можно использовать их для достижения своей цели.
4 ответа
Используйте фабрику, которую вы регистрируете в контейнере:
public class UserController : Controller
{
IUnitOfWorkFactory _factory;
public UserController(IUnitOfWorkFactory factory)
{
_factory = factory;
}
public ActionResult DoSomething()
{
using(var unitOfWork = _factory.Create())
{
return unitOfWork.GetRepository<IEmployeesRepository>().GetAllEmployees();
}
}
}
imho лучше абстрагироваться от UoW: http://blog.gauffin.org/2012/06/how-to-handle-transactions-in-asp-net-mvc3/
Вы можете легко сделать это с помощью Autofac. Я уверен, что другие контейнеры IoC должны иметь такую же функцию.
Вот ссылка на вики.
Пример кода:
public class UserController : Controller
{
Func<Owned<IUnitOfWork>> unitOfWorkFactory;
public UserController(Func<Owned<IUnitOfWork>> unitOfWorkFactory)
{
this.unitOfWorkFactory = unitOfWorkFactory;
}
public ActionResult DoSomething()
{
using(var unitOfWork = this.unitOfWorkFactory().Value)
{
return unitOfWork.GetRepository<IEmployeesRepository>().GetAllEmployees();
}
}
}
Никакой дополнительной регистрации не требуется, просто зарегистрируйте реализацию вашего интерфейса.
Вам не нужно создавать экземпляр переменной в блоке using, вы можете использовать существующую переменную. Итак, вы можете использовать метод инъекции, например так:
public ActionResult Index(IUnitOfWork unit)
{
using(unit)
{
// Do some work....
}
// Return an action
}
Просто поймите, что устройство будет утилизировано после выхода из блока использования, поэтому его не следует использовать.
[..] как я могу ввести его в предложении использования?
Там больше не будет using
пункт. Если контейнер IoC внедряет зависимость, он отвечает за срок ее службы.
Это плохая практика, что вы избавляетесь от зависимости (и using
делает именно это)
Я видел свойство инъекции и метод инъекции
Всегда используйте Constructor Injection, когда это возможно. Свойство / метод Injection используются в нескольких особых случаях.
Преимущества Constructor Injection в том, что класс сразу дает понять, каковы его зависимости. Кроме того, вы можете создать экземпляр только после предоставления всех необходимых зависимостей.
С Property Injection вы можете забыть установить необходимую зависимость. Используйте это только в том случае, если зависимость является необязательной, или имеет реализацию по умолчанию, или для разбиения циклических графов зависимостей.
С внедрением метода вы можете снова и снова вздувать код с одним и тем же параметром метода.
[...] что произойдет, если я захочу дважды использовать UnitOfWork в одном и том же экземпляре этого контроллера. Будет ли Ninject вводить его снова?
Ninject внедрит один и тот же экземпляр дважды или создаст два разных экземпляра, в зависимости от того, как вы проинструктировали его вести себя.
Контейнеры IoC позволяют указать / настроить стили времени жизни для внедренных компонентов. Для Ninject, посмотрите, как указать Области Объекта.