Я унаследовал некоторый код с UnitOfWorkFactory, который создает единицу работы внутри каждого метода репозитория. Проблема в том, что один метод репозитория редко является полной единицей работы, поэтому, если что-то пойдет не так, скажем, OrderService.PlaceOrder
, он не может просто откатить/отбросить эту единицу работы, поскольку это не одна единица.
Глядя на код, я думаю, что единица работы должна быть перемещена либо в класс обслуживания, либо в презентатора. Проблема, с которой я тогда сталкиваюсь, заключается в том, как мне передать ее либо в службу, либо в репозиторий? Ведущему передается экземпляр службы, а службе передается экземпляр репозитория.
Я мог бы создать единицу работы и внедрить в нее конструкторы сервисов, репозиториев и презентаторов, но тогда она осталась бы за рамками одной единицы работы. Это настольное приложение, поэтому презентатор и любые службы, которые он передает, могут быть активны для нескольких единиц работы.
Единственный способ, которым я могу передать единицу работы, - это добавить ее в качестве параметра ко всем методам службы/репозитория. Я не могу не думать, что должен быть лучший способ, чем этот, я что-то упустил?
Код выглядит примерно так:
Репозиторий:
class OrderRepository
{
public UnitOfWorkFactory UnitOfWorkFactory;
public OrderRepository(UnitOfWorkFactory unitOfWorkFactory)
{
UnitOfWorkFactory = unitOfWorkFactory;
}
public void Save(Order order)
{
using(var uow = UnitOfWorkFactory.Create())
{
// save order
uow.commit();
}
}
}
Сервис:
class OrderService
{
protected IOrderRepository OrderRepository;
protected IProductService ProductService;
public OrderService(IOrderRepository orderRepository, IProductRepository productService)
{
OrderRepository = orderRepository;
ProductService = productService;
}
public void PlaceOrder(Order order)
{
foreach(var item in order.Items)
{
if(!ProductService.IsInstock(item.Product, item.Quantity))
throw new ProductOutOfStockException(product);
ProductService.MarkForDispatch(item.Product, item.Quantity);
}
OrderRepository.Save(order);
}
public void CancelOrder(Order order)
{
ProductService.UnmarkForDispatch(item.Product, item.Quantity);
order.IsCanceled = true;
OrderRepository.Save(order);
}
}
Ведущий:
class OrderPresenter
{
protected IOrderView OrderView;
protected IOrderService OrderService;
public OrderPresenter(IOrderView orderView, IOrderService orderService)
{
OrderView = orderView;
OrderService = orderService;
}
public void PlaceOrder()
{
OrderService.PlaceOrder(order);
}
public void CanelOrder()
{
OrderService.CancelOrder(order);
}
}