将 IUnitOfWork 注册为 .net 核心中的服务

Registering IUnitOfWork As service in .net core

我将在我的 asp.net 核心 mvc 应用程序中实现存储库模式,为此我正在尝试一个简单的演示应用程序,其中包括存储库和工作单元概念。 我的第一个存储库

public  interface ICustomerRepository
{
    bool Add();

    bool Update();

    bool Delete();

}

 public class CustomerRepository:ICustomerRepository
{
    public bool Add()
    {
        return true;
    }

    public bool Update()
    {
        return true;
    }

    public bool Delete()
    {
        return true;
    }

}

第二个存储库

public interface IOrderRepository
    {
        bool Add();

        bool Update();

        bool Delete();
    }

public class OrderRepository:IOrderRepository
    {
        public bool Add()
        {
            return true;
        }

        public bool Update()
        {
            return true;
        }

        public bool Delete()
        {
            return true;
        }
    }

I 工作单元

public interface IUnitOfWork
{
    IOrderRepository Order {get;}

    ICustomerRepository Customer { get; }

    void Save();
    void Cancel();
}

public class UnitOfWork:IUnitOfWork
{
    public UnitOfWork(IOrderRepository order, ICustomerRepository customer)
    {
        Order = order;
        Customer = customer;
    }

    public  IOrderRepository Order { get; }

    public  ICustomerRepository Customer { get; }
    public void Save() { }
    public void Cancel() { }
}

在我的控制器中,

   public class HomeController : Controller
    {
        IUnitOfWork UW { get; }

        public HomeController(IUnitOfWork uw)
        {
            UW = uw;
        }

        public IActionResult Index()
        {
            UW.Customer.Add();
            UW.Order.Update();
            UW.Save();

            return View();
        }
}

我稍后会为 dapper 添加更多代码,但至少它应该可以正常工作而不会出现任何错误,但它给我错误

InvalidOperationException: Unable to resolve service for type 'CoreTS.Repository.UnitOfWork.IUnitOfWork' while attempting to activate 'CoreTS.Controllers.HomeController'.

有人建议我在 ConfigureService 方法下的 startup.cs 中添加 IUnitOfWork 作为服务,如

services.AddSingleton<IUnitOfWork, UnitOfWork>();

并且在添加这个之后另一个错误

InvalidOperationException: Unable to resolve service for type 'CoreTS.Repository.Order.IOrderRepository' while attempting to activate 'CoreTS.Repository.UnitOfWork.UnitOfWork'.

为了让它工作,我还必须在 startup.cs 和

中添加其他两个存储库
services.AddSingleton<IOrderRepository, OrderRepository>();
services.AddSingleton<ICustomerRepository, CustomerRepository>();

如果要有 n 个存储库,我必须将每个存储库都添加到 startup.cs 中(根据此代码),解决方案是什么。

所以

1.]这些错误是什么意思?

2.] 这里正确的配置是什么?

3.]这里不添加n个仓库作为服务的方法是什么?

注意:如前所述,这只是为了理解模式的流程,稍后我将在本文中添加 Dapper 或 EF Core 的代码

嗯,报错信息还是挺有意义的。 DI 容器必须解析 IUnitOfWork 的实例,该实例具有两个注入其构造函数的依赖项。所以DI容器也要解决这两个问题

asp.net-core 中没有允许您使用模式匹配或类似方式注册所有存储库的内置功能。您可以一一注册所有依赖项或使用 3rd 方库。

使用 Scrutor 你可以这样做:

services.Scan(scan => scan
                    .FromAssemblyOf<OrderRepository>()
                    .AddClasses(classes => classes.AssignableTo<IRepository>())
                    .AsImplementedInterfaces()
                    .WithSingletonLifetime());

请注意,要使其正常工作,所有存储库都必须实现 IRepository 接口(可以为空)

结论: 如果只有几个依赖项,我可能会一一注册它们,但是如果您打算稍后添加 N 个存储库 - 使用 3rd 方库。

  1. IUnitOfWork/IOrderRepository 的 IoC 容器中没有注册服务。您通过使用 AddSingleton 方法注册这些服务解决了这个问题。

  2. 不确定您所说的正确配置是什么意思,但是使用 AddSingleton/AddTransient/AddScoped 您正在将某些 类 注册为 IoC 容器中的服务。因此,当您注入某些东西(例如注入您的 HomeController)时,您正在使用映射到某些具体实现的接口。

  3. 您必须以某种方式注册服务,这就是您使用前面提到的方法所做的。如果你不注册它,它就不会被解析,当你试图激活一些其他依赖的服务时你会得到异常。如果您想在不显式注册某些服务的情况下注册某些服务,则必须扫描程序集并查找您要注册的类型。

What does these errors means ?

这些错误意味着您正在通过构造函数依赖注入使用服务,但您尚未将这些服务注册到 DI 解析器。

What will be the correct configuration here ?

您所做的是解决服务的正确方法。

What is the way to not to add n number of repository as service here?

您可以在单独的文件中按如下方式扩展 IServiceCollection

public static class ServiceCollectionExtensions
{
    public static IServiceCollection AddCustomServices(this IServiceCollection services,
        IConfiguration configuration)
    {

         services.AddSingleton<IUnitOfWork, UnitOfWork>();
         services.AddSingleton<IOrderRepository, OrderRepository>();
         services.AddSingleton<ICustomerRepository, CustomerRepository>();

         return services;
    }
}

然后在启动class如下:

services.AddCustomServices(Configuration);
  1. HomeController 的构造函数采用 IUnitOfWork,因此 ASP.NET Core 需要知道要为其提供什么实例,这就是为什么要在 ConfigureServices 中指定它。但是,您的 UnitOfWork class' 构造函数采用 IOrderRepository 和 ICustomerRepository,并且 ASP.NET Core 需要知道要提供哪些实例,因此您还必须在 ConfigureServices 中指定它们。

  2. 我认为你最终的配置是正确的,就目前而言,但它没有解决你的下一个问题...

  3. 没有 ASP.NET 核心依赖注入问题,您的模式已经存在问题。 UnitOfWork 的构造函数采用 2 个不同的参数,一个用于每个存储库。如果您想拥有 N 个不同的存储库,则该构造函数不再有效。相反,也许您需要引入 "repository manager" class 并将其注入构造函数(也将其添加到 ConfigureServices 中)。然后您需要设计 UnitOfWork 和 RepositoryManager 之间的关系,允许 UnitOfWork 与任何特定的存储库一起工作。