使用工作单元模式进行依赖注入

问题描述 投票:0回答:1

我正在尝试为我的 C#/.NET 存储库实现工作单元模式 (UoW)。我的计划是将 UoW 作为存储库的参数。这是一个如何使用它的示例:

using (var uow = new UnitOfWork())
{
    var itemRepository = new ItemRepository(uow);
    itemRepository.Add(new Item());
    uow.Commit();
}

此外,对于简单的操作(当不需要事务时),存储库应该能够在没有工作单元的情况下使用:

var itemRepository = new ItemRepository();
var item = itemRepository.Get(itemId);

UnitOfWork/Repository 可以从 ConnectionFactory 获取数据库连接。连接工厂通过依赖注入接收连接选项。但是,这是我的问题:存储库如何获取对 ConnectionFactory 实例的引用?

存储库是手动创建的,因此它们不能通过构造函数注入依赖项。一种选择是拥有存储库工厂,可以注入其依赖项。在这种情况下,用法可能是这样的:

using (var uow = new UnitOfWork())
{
    var itemRepository = itemRepositoryFactory.Create(uow);
    itemRepository.Add(new Item());
    uow.Commit();
}

该解决方案的缺点是每个存储库都需要自己的工厂,而且数量相当多。有没有其他解决方案可以解决这个问题?

c# .net dependency-injection repository unit-of-work
1个回答
0
投票

我肯定会将 UOW 注册为作用域依赖项。

作用域依赖项在创建它们的容器的生命周期内有效。通常,框架会从父容器生成子容器以执行某些工作。例如,ASP.NET Core 为请求生成一个子容器,然后在请求完成时将其释放。这意味着被注入的 UOW 实例与整个对象图中仅针对该请求的实例是相同的。

如果需要,您还可以创建自己的范围。例如,我已经这样做了两次:

  • 作业调度程序,以便每个作业都在自己的范围内运行
  • 消息处理程序,以便每条消息都在自己的范围内处理

这就是使用 Microsoft 的 DI 框架实现此目标的方法:

var collection = new ServiceCollection();
collection.AddScoped<IUnitOfWork, UnitOfWork>();

var provider = collection.BuildServiceProvider();

var puow = provider.GetRequiredService<IUnitOfWork>();

for(int i = 0; i < 2; i++)
{
    //Create the new scope
    using var childContainer = provider.CreateScope();

    //IUnitOfWork will be a singleton instance in this scope. 
    var c1uow = childContainer.ServiceProvider.GetRequiredService<IUnitOfWork>();
    var c2uow =  childContainer.ServiceProvider.GetRequiredService<IUnitOfWork>();
    // This should true, since they come from the same scope.
    var sameScope = c1uow == c2uow;
    
    //With the requested IUnitOfWork from provider instead, it would be a different instance
    //Therefore, this should be false    
    var diffScope = puow == c1uow;
}

这将允许您简单地将 IUnitOfWork 注入到每个存储库中,而无需为每个存储库创建一个工厂。

如果您在 ASP.NET Core 中编写应用程序,那么这将是开箱即用的。只需将依赖项注册为范围,就像这样

collection.AddScoped<IUnitOfWork, UnitOfWork>();

然后将其注入到您需要的存储库中。您不必担心创建新范围,因为框架会为应用程序收到的每个 http 请求执行此操作。

我强烈推荐阅读 Mark Seemann 的书《依赖注入原则、实践和模式》。它确实深入探讨了依赖注入是什么及其工作原理。不仅如此,我发现他是一位伟大的作家。

© www.soinside.com 2019 - 2024. All rights reserved.