【问题标题】:Injecting repository dependencies into a Unit of Work将存储库依赖项注入工作单元
【发布时间】:2023-03-23 02:10:02
【问题描述】:

我正在尝试在我的 asp.net MVC 项目中使用存储库和工作单元模式,但是我很难弄清楚如何将存储库依赖项传递给工作单元。工作单元的一般标准结构似乎如下:

public class UnitOfWork : IUnitOfWork
 {
        private ICustomerRepository _customerRepository;

        public ICustomerRepository CustomerRepository
        {
            get
            {
                if (this._customerRepository == null)
                {
                    this._customerRepository = new CustomerRepository(someContext);
                }
                return _customerRepository;
            }
        }
}

具体来说,让我感到困惑的是这一行:

this._customerRepository = new CustomerRepository(someContext);

通过为存储库定义接口,随着时间的推移和业务需求的变化,不就是能够将存储库依赖项注入 UoW 的整个想法吗?如果是这样,为什么我在网上看到的几乎每个实现都执行上述操作?在这个实现中,我们应该如何将ICustomerRepository 的新实例传递给 UoW?当然,我们还需要更改 UoW 中的代码,这不违反开放关闭原则吗?如何将存储库注入我的 UoW?

我环顾四周,之前似乎有人问过this question,但我仍然很难理解建议的解决方案(门面服务)。

【问题讨论】:

  • 对另一个问题的建议解决方案是避免在工作单元内引用存储库。然后引入了 Facade Service 来解决一个不同的问题,即“构造函数过度注入”。您还在哪里看到过这个实现?
  • 所以门面服务是为了解决一个完全不同的问题?我正在谈论的实现是我的问题中的代码块中的那个,just like this one,或其他数十篇针对 UoW 和 DI 的博客文章、文章和 SO 问题。
  • 据我了解,是的。有趣的是,我不知道这些实现,我总是看到类似this answer 的东西。

标签: c# dependency-injection repository-pattern unit-of-work


【解决方案1】:

有两种常用方法可以获取 CustomerRepository 的实例。 第一种方法称为构造函数注入,它是构造函数中的一个简单参数,例如

public class UnitOfWork : IUnitOfWork
{
    public UnitOfWork(ICustomerRepository repository)
    {
        _customerRepository = repository;
    }

    private ICustomerRepository _customerRepository;

    public ICustomerRepository CustomerRepository
    {
        get
        {
            if (this._customerRepository == null)
            {
                throw new ArgumentException("Missing repository");
            }
            return _customerRepository;
        }
    }
}

第二种更灵活的方法是使用 IoC 框架,如 Structuremap、Unity、Ninject... 等。

这是一个结构图的例子:

public class UnitOfWork : IUnitOfWork
{
    private ICustomerRepository _customerRepository;

    public ICustomerRepository CustomerRepository
    {
        get
        {
            if (this._customerRepository == null)
            {
                _customerRepository = ObjectFactory.GetInstance<ICustomerRepository>();
            }
            return _customerRepository;
        }
    }
}

另外,您需要一个配置类来告诉 Structuremap 要实例化哪个类,这可能看起来像这样:

public static class RepositoryRegistry
{
    internal static void DefaultConfiguration(Registry registry)
    {
       registry.For<ICustomerRepository>().Use<CustomerRepository>();
    }
}

【讨论】:

  • 太棒了。但是,为什么几乎所有声称将 repsoitory 和 UoW 与 DI 一起使用的在线示例和文章都倾向于使用我在问题中提到的方法,而不是您建议的(更合乎逻辑的)方法?
  • 也许是因为他们希望样本尽可能简单
  • 我会避免第二个建议,因为如果你这样做,你最终会隐藏对 IOC 容器的依赖作为服务定位器。同样在第一个方面,我建议对构造函数参数而不是属性 getter 进行空检查,因为 UOW 需要存储库,尽早失败并快速失败。
  • @Lukas 您的解决方案乍一看还不错,但有个问题,想想以后每次您要将新存储库添加到系统中时,您还需要更改 UnitOfWork 类。不是吗?
猜你喜欢
  • 2014-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-27
相关资源
最近更新 更多