如何使用依赖注入和仓储处理工作单元

4
我收到了一些代码,其中包含一个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);
    }
}

你是使用厚客户端还是薄客户端(如HTTP)? - jgauffin
@jgauffin 这是一个厚客户端。这是一个桌面应用程序,可以在本地处理所有业务规则。 - Sam
2个回答

2
我对这个问题没有简短的答案。您可以查看我之前写过的关于这个主题的博客文章,其中包含完整的答案。[又一篇UoW、仓储文章]
(如果您读了这篇文章,请告诉我您的想法)

这看起来是一个不错的解决方案。我最终做了一些微小的改动(见下文),但我会将其标记为答案,因为它也可以解决问题。 - Sam

2
我最终决定使用工厂并将其传递给工作单元。然后,工厂使用传递的UOW创建其他所有内容。

这是我最终做的:

存储库:

public class Repository : IRepoository
{
    IUnitOfWork UnitOfWork;

    public Repository(IUnitOfWork uow)
    {
        UnitOfWork = uow;
    }

    public void SomeOtherMethod(int id)
    {
        // Do something
    }
}

服务:

public class Service : IService
{
    IUnitOfWork UnitOfWork;
    IRepoository Repository;

    public Service(IUnitOfWork uow, IRepoository repository)
    {
        UnitOfWork = uow;
        Repository = repository;
    }

    public void SomeMethod(int id)
    {
        Repository.SomeOtherMethod(id);
        // do other stuff
    }
}

工厂:

public class IUnitOfWorkFactory
{
    IUnitOfWork Create();
}

public class IServiceFactory
{
    IService Create(IUnitOfWork uow);
}
IServiceFactory.Create方法创建了一个服务和该服务所依赖的仓储,并将它们都传递给了已传入的工作单元。
演示者:
public class Presenter
{
    protected UnitOfWorkFactory UnitOfWorkFactory;
    protected IServiceFactory ServiceFactory;

    public Presenter(IUnitOfWorkFactory unitOfWorkFactory, IServiceFactory serviceFactory)
    {
        UnitOfWorkFactory = unitOfWorkFactory;
        ServiceFactory = serviceFactory;
    }

    public void DoSomething()
    {
        // Get a new UOW from the factory
        using(var uow = unitOfWorkFactory.Create())
        {
            // Then create the service and repository with the new UOW via the ServiceFactory
            var service = serviceFactory.Create(uow);
            service.SomeMethod(20);

            uow.Commit();
        }
    }
}

这似乎也是一个不错的解决方案,但是你需要为每个服务创建一个工厂。如果我最终在我的帖子中加入了你的一些想法,我会记得给你信用。 - Ibrahim Najjar
1
是的,这种方法的缺点就是如此。对我来说并不是问题,因为代码使用库进行依赖注入,所以我可以创建一个通用工厂接口,接受 UOW 并自动创建实现。您也可以手动创建通用工厂来轻松完成此操作。 - Sam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接