各リポジトリメソッド内に作業単位を作成するUnitOfWorkFactoryを持つコードを継承しました。問題は、単一のリポジトリメソッドが完全な作業単位になることはめったにないため、何か問題が発生した場合、OrderService.PlaceOrder
その作業単位は1つの単位ではないため、ロールバック/破棄できないことです。
コードを見ると、作業単位をサービスクラスまたはプレゼンターのいずれかに移動する必要があると思います。私が抱えている問題は、それをサービスまたはリポジトリに渡す方法です。プレゼンターにはサービスのインスタンスが渡され、サービスにはリポジトリのインスタンスが渡されます。
作業単位を作成して、サービス、リポジトリー、およびプレゼンターのコンストラクターを注入することはできますが、それでは単一の作業単位を超えて生きることになります。これはデスクトップアプリであるため、プレゼンターとそれが渡すすべてのサービスは、複数の作業単位で存続できます。
作業単位を渡すことができると私が考える唯一の方法は、それをすべてのサービス/リポジトリメソッドにパラメータとして追加することです。それよりも良い方法があるはずだと思わずにはいられませんが、何かが足りないのでしょうか。
コードは次のようになります。
リポジトリ:
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);
}
}