将 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 方库。
IUnitOfWork
/IOrderRepository
的 IoC 容器中没有注册服务。您通过使用 AddSingleton 方法注册这些服务解决了这个问题。
不确定您所说的正确配置是什么意思,但是使用 AddSingleton/AddTransient/AddScoped 您正在将某些 类 注册为 IoC 容器中的服务。因此,当您注入某些东西(例如注入您的 HomeController)时,您正在使用映射到某些具体实现的接口。
您必须以某种方式注册服务,这就是您使用前面提到的方法所做的。如果你不注册它,它就不会被解析,当你试图激活一些其他依赖的服务时你会得到异常。如果您想在不显式注册某些服务的情况下注册某些服务,则必须扫描程序集并查找您要注册的类型。
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);
HomeController 的构造函数采用 IUnitOfWork,因此 ASP.NET Core 需要知道要为其提供什么实例,这就是为什么要在 ConfigureServices 中指定它。但是,您的 UnitOfWork class' 构造函数采用 IOrderRepository 和 ICustomerRepository,并且 ASP.NET Core 需要知道要提供哪些实例,因此您还必须在 ConfigureServices 中指定它们。
我认为你最终的配置是正确的,就目前而言,但它没有解决你的下一个问题...
没有 ASP.NET 核心依赖注入问题,您的模式已经存在问题。 UnitOfWork 的构造函数采用 2 个不同的参数,一个用于每个存储库。如果您想拥有 N 个不同的存储库,则该构造函数不再有效。相反,也许您需要引入 "repository manager" class 并将其注入构造函数(也将其添加到 ConfigureServices 中)。然后您需要设计 UnitOfWork 和 RepositoryManager 之间的关系,允许 UnitOfWork 与任何特定的存储库一起工作。
我将在我的 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 方库。
IUnitOfWork
/IOrderRepository
的 IoC 容器中没有注册服务。您通过使用 AddSingleton 方法注册这些服务解决了这个问题。不确定您所说的正确配置是什么意思,但是使用 AddSingleton/AddTransient/AddScoped 您正在将某些 类 注册为 IoC 容器中的服务。因此,当您注入某些东西(例如注入您的 HomeController)时,您正在使用映射到某些具体实现的接口。
您必须以某种方式注册服务,这就是您使用前面提到的方法所做的。如果你不注册它,它就不会被解析,当你试图激活一些其他依赖的服务时你会得到异常。如果您想在不显式注册某些服务的情况下注册某些服务,则必须扫描程序集并查找您要注册的类型。
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);
HomeController 的构造函数采用 IUnitOfWork,因此 ASP.NET Core 需要知道要为其提供什么实例,这就是为什么要在 ConfigureServices 中指定它。但是,您的 UnitOfWork class' 构造函数采用 IOrderRepository 和 ICustomerRepository,并且 ASP.NET Core 需要知道要提供哪些实例,因此您还必须在 ConfigureServices 中指定它们。
我认为你最终的配置是正确的,就目前而言,但它没有解决你的下一个问题...
没有 ASP.NET 核心依赖注入问题,您的模式已经存在问题。 UnitOfWork 的构造函数采用 2 个不同的参数,一个用于每个存储库。如果您想拥有 N 个不同的存储库,则该构造函数不再有效。相反,也许您需要引入 "repository manager" class 并将其注入构造函数(也将其添加到 ConfigureServices 中)。然后您需要设计 UnitOfWork 和 RepositoryManager 之间的关系,允许 UnitOfWork 与任何特定的存储库一起工作。