EF 6 的工作单元和依赖注入设计问题
Unit of work with EF 6 and Dependency injection Design problems
我用entity framework6开发web应用,在设计应用结构上有困难。我的主要问题是在我的具体情况下如何处理依赖注入。
下面的代码是我希望应用程序的样子。我正在使用 Autofac,但我想它对每个 DI 用户来说都足够基本了:
public interface IUnitOfWork
{
bool Commit();
}
public class UnitOfWork : IUnitOfWork, IDisposable
{
private DbContext _context;
public UnitOfWork(DbContext context)
{
_context = context;
}
public bool Commit()
{
// ..
}
public bool Dispose()
{
_context.Dispose();
}
}
public class ProductsController : ApiController
{
public ProductsController(IProductsManager managet)
}
public class ProductsManager : IProductsManager
{
private Func<Owned<IUnitOfWork>> _uowFactory;
private IProductsDataService _dataService;
public Manager(Func<Owned<IUnitOfWork>> uowFactory, IProductsDataService dataService)
{
_dataService = dataService;
_uowFactory = uowFactory;
}
public bool AddProduct(ProductEntity product)
{
using (ownedUow = _uowFactory())
{
var uow = ownedUow.Value;
var addedProduct = _dataService.AddProduct(product);
if (addedProduct != null)
uow.Commit();
}
}
}
public interface IProductsDataService
{
ProductEntity AddProduct (Product product)
}
public class ProductsDataService : IProductsDataService
{
private IRepositoriesFactory _reposFactory;
public DataService(IRepositoriesFactory reposFactory)
{
_reposFactory = reposFactory;
}
public ProductEntity AddProduct(ProductEntity product)
{
var repo = reposFactory.Get<IProductsRepository>();
return repo.AddProduct(product);
}
}
public interface IRepositoriesFactory
{
T Get<T>() where T : IRepository
}
public class RepositoriesFactory : IRepositoriesFactory
{
private ILifetimeScope _scope;
public RepositoriesFactory(ILifetimeScope scope)
{
_scope = scope;
}
public T Get<T>() where T : IRepository
{
return _scope.Resolve<T>();
}
}
public interface IProductsRepository
{
ProductEntity AddProduct(ProductEntity);
}
public ProductsRepository : IProductsRepository
{
private DbContext _context;
public ProductsRepository(DbContext context)
{
_context = context;
}
public ProductEntity AddProduct(ProductEntity)
{
// Implementation..
}
}
这是我认为理想的实现,但我不知道如何实现,因为我的 ProductsDataService 是单例的,因此它与由工程单元工厂创建的 Owned 范围无关。
有没有一种方法可以关联要创建的存储库,并在它们的构造函数中采用为工作单元创建的相同 DbContext?以某种方式更改 RepositoriesFactory 中的代码?
目前我所拥有的是工作单元包含存储库工厂,因此存储库中的上下文将与工作单元中的上下文相同(我根据范围注册了 DbContext),
经理现在也负责 DataService 的工作,这是我不喜欢的。
我知道我可以绕过 UnitOfWork - 方法注入到 DataService 方法,但我宁愿使用 Ctor 注入,因为我认为它看起来更好。
我想要的是将其分开 - 一个管理器,它的工作是实例化工作单元并在需要时提交它们,另一个 class (DataService) 实际执行逻辑。
无论如何,如果您有任何改进意见/想法,我想听听您对这个实现的看法。
感谢您的宝贵时间!
编辑:这就是我最终得到的:
public interface IUnitOfWork
{
bool Commit();
}
public class DatabaseUnitOfWork : IUnitOfWork
{
private DbContext _context;
public DatabaseUnitOfWork(DbContext context)
{
_context = context;
}
public bool Commit()
{
// ..
}
}
// Singleton
public class ProductsManager : IProductsManager
{
private Func<Owned<IProductsDataService>> _uowFactory;
public ProductsManager(Func<Owned<IProductsDataService>> uowFactory)
{
_uowFactory = uowFactory;
}
public bool AddProduct(ProductEntity product)
{
using (ownedUow = _uowFactory())
{
var dataService = ownedUow.Value;
var addedProduct = _dataService.AddProduct(product);
if (addedProduct != null)
uow.Commit();
}
}
}
public interface IProductsDataService : IUnitOfWork
{
ProductEntity AddProduct (Product product)
}
public class ProductsDataService : DatabaseUnitOfWork, IDataService
{
private IRepositoriesFactory _reposFactory;
public DataService(IRepositoriesFactory reposFactory)
{
_reposFactory = reposFactory;
}
public ProductEntity AddProduct(ProductEntity product)
{
var repo = _reposFactory .Get<IProductsRepository>();
return repo.AddProduct(product);
}
}
public interface IRepositoriesFactory
{
Get<T>() where T : IRepository
}
public class RepositoriesFactory : IRepositoriesFactory
{
private ILifetimeScope _scope;
public RepositoriesFactory(ILifetimeScope scope)
{
_scope = scope;
}
public Get<T>() where T : IRepository
{
return _scope.Resolve<T>();
}
}
public interface IProductsRepository
{
ProductEntity AddProduct(ProductEntity);
}
public ProductsRepository : IProductsRepository
{
private DbContext _context;
public ProductsRepository(DbContext context)
{
_context = context;
}
public ProductEntity AddProduct(ProductEntity)
{
// Implementation..
}
}
看来问题并不是真正确保注入 UnitOfWork
和 ProductsRepository
的 DbContext 实例相同。
这可以通过将 DbContext 注册为 InstancePerLifetimeScope
并在解析 IUnitOfWork
和 ProductsRepository
之前创建一个新的 LifetimeScope
来实现。
任何不属于您的依赖项将在处置 LifetimeScope
.
时被处置
问题似乎是您在这两者之间没有明确的关系 类。您的 UoW 不依赖于 'any DbContext',它取决于当前事务中涉及的任何 DbContext。具体那个。
你的 UoW 和知识库之间也没有直接关系。这看起来不像 UoW pattern。
我无法确定谁将处置您的 IRepositoryFactory
创建的 IRepository
。您正在使用容器来解决它(通过您注入 RepositoriesFactory
的 ILifetimeScope
)。除非从 Factory
中获取该实例的人处置它,否则只能通过处置注入 IRepositoryFactory
.
的 LifetimeScope
来处置它
另一个可能出现的问题是 DbContext 的所有权。您可以通过 IUnitOfWork
上的 Dispose 在那个 using
块上处理它。但是您的 UnitOfWork
也不拥有该实例。容器可以。存储库还会尝试处理 DbContext 吗?他们还通过构造函数注入接收。
我建议重新考虑这个解决方案。
我同意 Bruno Garcia 关于您的代码问题的建议。但是,我发现它还有其他一些问题。
首先我会说我没有像您那样明确地使用工作单元模式,但我确实理解您的目的。
Bruno 没有解决的问题是你的关注点分离很差。他稍微暗示了一下,我会解释更多:您的控制器中有两个独立的竞争对象,它们都试图利用相同的资源 (DbContext)。正如他所说,您要做的是为每个请求设置一个 DbContext。但是,这有一个问题:在处理 UnitOfWork 后,没有什么可以阻止 Controller 尝试继续使用 ProductsRepository。如果这样做,则与数据库的连接已被释放。
因为您有两个对象需要使用相同的资源,所以您应该在一个对象封装另一个对象的地方重新构建它。这也提供了一个额外的好处,即向控制器隐藏任何关于数据传播的问题。
控制器应该知道的只是您的服务对象,它应该包含所有业务逻辑以及存储库及其工作单元的网关,同时保持它对服务的消费者不可见。这样,Controller 只需担心处理和处置一个对象。
解决此问题的其他方法之一是让 ProductsRepository 从 UnitOfWork 派生,这样您就不必担心任何重复的代码。
然后,在您的 AddProduct
方法中,您将调用 _context.SaveChanges()
,然后将该对象沿着管道返回到您的控制器。
UPDATE(大括号的样式是为了紧凑)
这是您想要执行的布局:
UnitOfWork 是最底层,包括与数据库的连接。但是,将此设置为 abstract
,因为您不想允许它的具体实现。您不再需要接口,因为您在 Commit
方法中所做的事情永远不会暴露,并且对象的保存应该在方法中完成。我会展示如何下线。
public abstract class UnitOfWork : IDisposable {
private DbContext _context;
public UnitOfWork(DbContext context) {
_context = context;
}
protected bool Commit() {
// ... (Assuming this is calling _context.SaveChanges())
}
public bool Dispose() {
_context.Dispose();
}
}
您的存储库在下一层。从 UnitOfWork
派生,以便它继承所有行为,并且对于每个特定类型都是相同的。
public interface IProductsRepository {
ProductEntity AddProduct(ProductEntity product);
}
public ProductsRepository: UnitOfWork, IProductsRepository {
public ProductsRepository(DbContext context) : base(context) { }
public ProductEntity AddProduct(ProductEntity product) {
// Don't forget to check here. Only do that where you're using it.
if (product == null) {
throw new ArgumentNullException(nameof(product));
}
var newProduct = // Implementation...
if (newProduct != null) {
Commit();
}
return newProduct;
}
}
有了它,您现在关心的只是拥有您的 ProductsRepository。在您的 DataService 层中,利用依赖注入并仅传递 ProductsRepository 本身。如果你真的打算使用工厂,那么通过工厂,但你的成员变量仍然是 IProductsRepository
。不要让每个方法都必须弄清楚。
不要忘记让 所有 接口派生自 IDisposable
public interface IProductsDataService : IDisposable {
ProductEntity AddProduct(ProductEntity product);
}
public class ProductsDataService : IProductsDataService {
private IProductsRepository _repository;
public ProductsDataService(IProductsRepository repository) {
_repository = repository;
}
public ProductEntity AddProduct(ProductEntity product) {
return _repository.AddProduct(product);
}
public bool Dispose() {
_repository.Dispose();
}
}
如果您坚决要使用 ProductsManager
,您可以,但它只是另一层,不再提供太多好处。 class.
同样的交易
我会按照我的意愿完成你的控制器。
public class ProductsController : Controller {
private IProductsDataService _service;
public ProductsController(IProductsDataService service) {
_service = service;
}
protected override void Dispose(bool disposing) {
_service.Dispose();
base.Dispose(disposing);
}
// Or whatever you're using it as.
[HttpPost]
public ActionResult AddProduct(ProductEntity product) {
var newProduct = _service.AddProduct(product);
return View(newProduct);
}
}
您不希望在单例实例中使用单例 DbContext
。没关系,可以用工厂来完成。另外你想分享这个 DbContext
。这也可以,您可以解决 return DbContext
与工厂相关的生命周期。 问题是;您希望在单个实例中共享非单例 DbContext
而无需管理生命周期(Tcp/Ip 请求)。
ProductService
和ProductManager
是单例的原因是什么?
我建议你在每个生命周期中使用 ProductService
和 ProductManager
。当你有 http 请求时,它很好。当您有 tcp/ip 请求时,您可以开始新的生命周期范围(尽可能最高级别)然后在那里解析 ProductManager
。
更新:我在评论中提到的解决方案 1 的代码。
Managers
必须是单身人士(如您所说)。
除 managers
之外,您应该将 dbcontext
、services
、repositories
和 Uow
注册为 per lifetime
范围。
我们可以这样初始化:
public class ProductsManager : IProductsManager
{
//This is kind of service locator. We hide Uow and ProductDataService dependencies.
private readonly ILifetimeScope _lifetimeScope;
public ProductsManager(ILifetimeScope lifetimeScope)
{
_lifetimeScope = lifetimeScope;
}
}
但这是一种服务定位器。我们隐藏 Uow
和 ProductDataService
依赖项。
所以我们应该实现一个提供者:
public IProductsManagerProvider : IProductsManager
{
}
public class ProductsManagerProvider : IProductsManagerProvider
{
private readonly IUnitOfWork _uow;
private readonly IProductsDataService _dataService;
public ProductsManagerProvider (IUnitOfWork uow, IProductsDataService dataService)
{
_dataService = dataService;
_uow = uow;
}
public bool AddProduct(ProductEntity product)
{
var result=false;
var addedProduct = _dataService.AddProduct(product);
if (addedProduct != null)
result=_uow.Commit()>0;
return result;
}
}
然后我们将其注册为per dependency
(因为我们将在工厂中使用它)。
container.RegisterType<ProductsManagerProvider>().As<IProductsManagerProvider>().InstancePerDependency();
你的ProductsManager
class应该是这样的。 (现在我们不隐藏任何依赖项)。
public class ProductsManager : IProductsManager
{
private readonly Func<Owned<IProductsManagerProvider>> _managerProvider;
//Now we don't hide any dependencies.
public ProductsManager(Func<Owned<IProductsManagerProvider>> managerProvider)
{
_managerProvider = managerProvider;
}
public bool AddProduct(ProductEntity product)
{
using (var provider = _managerProvider())
{
return provider.Value.AddProduct(product);
}
}
}
我用自己的 classes 进行了测试。
您有单例管理器实例,它有一个工厂来创建管理器提供程序。 Manager Providers 是每个依赖项,因为每次我们都应该在单例中获取新实例。每个生命周期提供者中的所有内容,因此它们的生命周期是每个依赖生命周期的连接提供者。
当您在管理器中添加产品时 Container
创建 1 个 Provider
、1 个 DbContext
、1 个 DataService
和 1 个 Uow
(DbContext
是共享)。 Provider
在 Manager
.
中的方法 return 之后与所有已实现的实例 (DbContex、Uow、DataService) 一起处理(每个依赖项)
我用entity framework6开发web应用,在设计应用结构上有困难。我的主要问题是在我的具体情况下如何处理依赖注入。
下面的代码是我希望应用程序的样子。我正在使用 Autofac,但我想它对每个 DI 用户来说都足够基本了:
public interface IUnitOfWork
{
bool Commit();
}
public class UnitOfWork : IUnitOfWork, IDisposable
{
private DbContext _context;
public UnitOfWork(DbContext context)
{
_context = context;
}
public bool Commit()
{
// ..
}
public bool Dispose()
{
_context.Dispose();
}
}
public class ProductsController : ApiController
{
public ProductsController(IProductsManager managet)
}
public class ProductsManager : IProductsManager
{
private Func<Owned<IUnitOfWork>> _uowFactory;
private IProductsDataService _dataService;
public Manager(Func<Owned<IUnitOfWork>> uowFactory, IProductsDataService dataService)
{
_dataService = dataService;
_uowFactory = uowFactory;
}
public bool AddProduct(ProductEntity product)
{
using (ownedUow = _uowFactory())
{
var uow = ownedUow.Value;
var addedProduct = _dataService.AddProduct(product);
if (addedProduct != null)
uow.Commit();
}
}
}
public interface IProductsDataService
{
ProductEntity AddProduct (Product product)
}
public class ProductsDataService : IProductsDataService
{
private IRepositoriesFactory _reposFactory;
public DataService(IRepositoriesFactory reposFactory)
{
_reposFactory = reposFactory;
}
public ProductEntity AddProduct(ProductEntity product)
{
var repo = reposFactory.Get<IProductsRepository>();
return repo.AddProduct(product);
}
}
public interface IRepositoriesFactory
{
T Get<T>() where T : IRepository
}
public class RepositoriesFactory : IRepositoriesFactory
{
private ILifetimeScope _scope;
public RepositoriesFactory(ILifetimeScope scope)
{
_scope = scope;
}
public T Get<T>() where T : IRepository
{
return _scope.Resolve<T>();
}
}
public interface IProductsRepository
{
ProductEntity AddProduct(ProductEntity);
}
public ProductsRepository : IProductsRepository
{
private DbContext _context;
public ProductsRepository(DbContext context)
{
_context = context;
}
public ProductEntity AddProduct(ProductEntity)
{
// Implementation..
}
}
这是我认为理想的实现,但我不知道如何实现,因为我的 ProductsDataService 是单例的,因此它与由工程单元工厂创建的 Owned 范围无关。 有没有一种方法可以关联要创建的存储库,并在它们的构造函数中采用为工作单元创建的相同 DbContext?以某种方式更改 RepositoriesFactory 中的代码?
目前我所拥有的是工作单元包含存储库工厂,因此存储库中的上下文将与工作单元中的上下文相同(我根据范围注册了 DbContext), 经理现在也负责 DataService 的工作,这是我不喜欢的。
我知道我可以绕过 UnitOfWork - 方法注入到 DataService 方法,但我宁愿使用 Ctor 注入,因为我认为它看起来更好。
我想要的是将其分开 - 一个管理器,它的工作是实例化工作单元并在需要时提交它们,另一个 class (DataService) 实际执行逻辑。
无论如何,如果您有任何改进意见/想法,我想听听您对这个实现的看法。
感谢您的宝贵时间!
编辑:这就是我最终得到的:
public interface IUnitOfWork
{
bool Commit();
}
public class DatabaseUnitOfWork : IUnitOfWork
{
private DbContext _context;
public DatabaseUnitOfWork(DbContext context)
{
_context = context;
}
public bool Commit()
{
// ..
}
}
// Singleton
public class ProductsManager : IProductsManager
{
private Func<Owned<IProductsDataService>> _uowFactory;
public ProductsManager(Func<Owned<IProductsDataService>> uowFactory)
{
_uowFactory = uowFactory;
}
public bool AddProduct(ProductEntity product)
{
using (ownedUow = _uowFactory())
{
var dataService = ownedUow.Value;
var addedProduct = _dataService.AddProduct(product);
if (addedProduct != null)
uow.Commit();
}
}
}
public interface IProductsDataService : IUnitOfWork
{
ProductEntity AddProduct (Product product)
}
public class ProductsDataService : DatabaseUnitOfWork, IDataService
{
private IRepositoriesFactory _reposFactory;
public DataService(IRepositoriesFactory reposFactory)
{
_reposFactory = reposFactory;
}
public ProductEntity AddProduct(ProductEntity product)
{
var repo = _reposFactory .Get<IProductsRepository>();
return repo.AddProduct(product);
}
}
public interface IRepositoriesFactory
{
Get<T>() where T : IRepository
}
public class RepositoriesFactory : IRepositoriesFactory
{
private ILifetimeScope _scope;
public RepositoriesFactory(ILifetimeScope scope)
{
_scope = scope;
}
public Get<T>() where T : IRepository
{
return _scope.Resolve<T>();
}
}
public interface IProductsRepository
{
ProductEntity AddProduct(ProductEntity);
}
public ProductsRepository : IProductsRepository
{
private DbContext _context;
public ProductsRepository(DbContext context)
{
_context = context;
}
public ProductEntity AddProduct(ProductEntity)
{
// Implementation..
}
}
看来问题并不是真正确保注入 UnitOfWork
和 ProductsRepository
的 DbContext 实例相同。
这可以通过将 DbContext 注册为 InstancePerLifetimeScope
并在解析 IUnitOfWork
和 ProductsRepository
之前创建一个新的 LifetimeScope
来实现。
任何不属于您的依赖项将在处置 LifetimeScope
.
问题似乎是您在这两者之间没有明确的关系 类。您的 UoW 不依赖于 'any DbContext',它取决于当前事务中涉及的任何 DbContext。具体那个。
你的 UoW 和知识库之间也没有直接关系。这看起来不像 UoW pattern。
我无法确定谁将处置您的 IRepositoryFactory
创建的 IRepository
。您正在使用容器来解决它(通过您注入 RepositoriesFactory
的 ILifetimeScope
)。除非从 Factory
中获取该实例的人处置它,否则只能通过处置注入 IRepositoryFactory
.
LifetimeScope
来处置它
另一个可能出现的问题是 DbContext 的所有权。您可以通过 IUnitOfWork
上的 Dispose 在那个 using
块上处理它。但是您的 UnitOfWork
也不拥有该实例。容器可以。存储库还会尝试处理 DbContext 吗?他们还通过构造函数注入接收。
我建议重新考虑这个解决方案。
我同意 Bruno Garcia 关于您的代码问题的建议。但是,我发现它还有其他一些问题。
首先我会说我没有像您那样明确地使用工作单元模式,但我确实理解您的目的。
Bruno 没有解决的问题是你的关注点分离很差。他稍微暗示了一下,我会解释更多:您的控制器中有两个独立的竞争对象,它们都试图利用相同的资源 (DbContext)。正如他所说,您要做的是为每个请求设置一个 DbContext。但是,这有一个问题:在处理 UnitOfWork 后,没有什么可以阻止 Controller 尝试继续使用 ProductsRepository。如果这样做,则与数据库的连接已被释放。
因为您有两个对象需要使用相同的资源,所以您应该在一个对象封装另一个对象的地方重新构建它。这也提供了一个额外的好处,即向控制器隐藏任何关于数据传播的问题。
控制器应该知道的只是您的服务对象,它应该包含所有业务逻辑以及存储库及其工作单元的网关,同时保持它对服务的消费者不可见。这样,Controller 只需担心处理和处置一个对象。
解决此问题的其他方法之一是让 ProductsRepository 从 UnitOfWork 派生,这样您就不必担心任何重复的代码。
然后,在您的 AddProduct
方法中,您将调用 _context.SaveChanges()
,然后将该对象沿着管道返回到您的控制器。
UPDATE(大括号的样式是为了紧凑)
这是您想要执行的布局:
UnitOfWork 是最底层,包括与数据库的连接。但是,将此设置为 abstract
,因为您不想允许它的具体实现。您不再需要接口,因为您在 Commit
方法中所做的事情永远不会暴露,并且对象的保存应该在方法中完成。我会展示如何下线。
public abstract class UnitOfWork : IDisposable {
private DbContext _context;
public UnitOfWork(DbContext context) {
_context = context;
}
protected bool Commit() {
// ... (Assuming this is calling _context.SaveChanges())
}
public bool Dispose() {
_context.Dispose();
}
}
您的存储库在下一层。从 UnitOfWork
派生,以便它继承所有行为,并且对于每个特定类型都是相同的。
public interface IProductsRepository {
ProductEntity AddProduct(ProductEntity product);
}
public ProductsRepository: UnitOfWork, IProductsRepository {
public ProductsRepository(DbContext context) : base(context) { }
public ProductEntity AddProduct(ProductEntity product) {
// Don't forget to check here. Only do that where you're using it.
if (product == null) {
throw new ArgumentNullException(nameof(product));
}
var newProduct = // Implementation...
if (newProduct != null) {
Commit();
}
return newProduct;
}
}
有了它,您现在关心的只是拥有您的 ProductsRepository。在您的 DataService 层中,利用依赖注入并仅传递 ProductsRepository 本身。如果你真的打算使用工厂,那么通过工厂,但你的成员变量仍然是 IProductsRepository
。不要让每个方法都必须弄清楚。
不要忘记让 所有 接口派生自 IDisposable
public interface IProductsDataService : IDisposable {
ProductEntity AddProduct(ProductEntity product);
}
public class ProductsDataService : IProductsDataService {
private IProductsRepository _repository;
public ProductsDataService(IProductsRepository repository) {
_repository = repository;
}
public ProductEntity AddProduct(ProductEntity product) {
return _repository.AddProduct(product);
}
public bool Dispose() {
_repository.Dispose();
}
}
如果您坚决要使用 ProductsManager
,您可以,但它只是另一层,不再提供太多好处。 class.
我会按照我的意愿完成你的控制器。
public class ProductsController : Controller {
private IProductsDataService _service;
public ProductsController(IProductsDataService service) {
_service = service;
}
protected override void Dispose(bool disposing) {
_service.Dispose();
base.Dispose(disposing);
}
// Or whatever you're using it as.
[HttpPost]
public ActionResult AddProduct(ProductEntity product) {
var newProduct = _service.AddProduct(product);
return View(newProduct);
}
}
您不希望在单例实例中使用单例 DbContext
。没关系,可以用工厂来完成。另外你想分享这个 DbContext
。这也可以,您可以解决 return DbContext
与工厂相关的生命周期。 问题是;您希望在单个实例中共享非单例 DbContext
而无需管理生命周期(Tcp/Ip 请求)。
ProductService
和ProductManager
是单例的原因是什么?
我建议你在每个生命周期中使用 ProductService
和 ProductManager
。当你有 http 请求时,它很好。当您有 tcp/ip 请求时,您可以开始新的生命周期范围(尽可能最高级别)然后在那里解析 ProductManager
。
更新:我在评论中提到的解决方案 1 的代码。
Managers
必须是单身人士(如您所说)。
除 managers
之外,您应该将 dbcontext
、services
、repositories
和 Uow
注册为 per lifetime
范围。
我们可以这样初始化:
public class ProductsManager : IProductsManager
{
//This is kind of service locator. We hide Uow and ProductDataService dependencies.
private readonly ILifetimeScope _lifetimeScope;
public ProductsManager(ILifetimeScope lifetimeScope)
{
_lifetimeScope = lifetimeScope;
}
}
但这是一种服务定位器。我们隐藏 Uow
和 ProductDataService
依赖项。
所以我们应该实现一个提供者:
public IProductsManagerProvider : IProductsManager
{
}
public class ProductsManagerProvider : IProductsManagerProvider
{
private readonly IUnitOfWork _uow;
private readonly IProductsDataService _dataService;
public ProductsManagerProvider (IUnitOfWork uow, IProductsDataService dataService)
{
_dataService = dataService;
_uow = uow;
}
public bool AddProduct(ProductEntity product)
{
var result=false;
var addedProduct = _dataService.AddProduct(product);
if (addedProduct != null)
result=_uow.Commit()>0;
return result;
}
}
然后我们将其注册为per dependency
(因为我们将在工厂中使用它)。
container.RegisterType<ProductsManagerProvider>().As<IProductsManagerProvider>().InstancePerDependency();
你的ProductsManager
class应该是这样的。 (现在我们不隐藏任何依赖项)。
public class ProductsManager : IProductsManager
{
private readonly Func<Owned<IProductsManagerProvider>> _managerProvider;
//Now we don't hide any dependencies.
public ProductsManager(Func<Owned<IProductsManagerProvider>> managerProvider)
{
_managerProvider = managerProvider;
}
public bool AddProduct(ProductEntity product)
{
using (var provider = _managerProvider())
{
return provider.Value.AddProduct(product);
}
}
}
我用自己的 classes 进行了测试。
您有单例管理器实例,它有一个工厂来创建管理器提供程序。 Manager Providers 是每个依赖项,因为每次我们都应该在单例中获取新实例。每个生命周期提供者中的所有内容,因此它们的生命周期是每个依赖生命周期的连接提供者。
当您在管理器中添加产品时 Container
创建 1 个 Provider
、1 个 DbContext
、1 个 DataService
和 1 个 Uow
(DbContext
是共享)。 Provider
在 Manager
.