1

我是 DI 的新手,我正在开发一个 MVC 项目,其中一个控制器被注入了一个UnitOfWork,这个 UnitOfWork 包含我域中每个实体类型的存储库。使用MSDN作为指南,我最初有类似的东西

public IRepository<Employee> Employees {
    get {
        if (_employees == null) {
            _employees = new SqlRepository<Employee>(_context);
        }
        return _employees;
    }
}

但是,我认为注入存储库会很好,例如:

public SqlUnitOfWork(IRepository<Employee> employees)
{
    this.Employees = employees;
}

但是,如果创建 SqlRepository 非常昂贵怎么办。并非每个控制器操作都使用每个存储库。在我更改为 DI 之前,只有在访问它们时才会创建每个存储库。但是,现在所有存储库都是使用 UnitOfWork 创建的。我正在尝试确定当我已经在 SqlUnitOfWork 中时注入 SqlRepositories 是否值得?或者,我应该遵循 MSDN 示例吗?

4

3 回答 3

1

我不是 ASP.NET MVC 用户,但依赖注入方法背后的想法并没有改变。所以,把这个和一粒盐一起吃

根据您的描述,您在工作单元中使用了多个存储库,您无法决定是注入它们还是在其中创建它们。最好的做法是:两者都不是

当您处理未知数量的相同类型的依赖项时,注入工厂实例会更聪明。然后,您的UnitOfWork实施可以向所述工厂请求服务。

在这种情况下,工厂将检查此类服务是否已经初始化。如果此类服务已初始化,您可以将其返回。如果没有,则初始化该服务,将其缓存(很可能在工厂中的某些类似数组的结构中)并返回该实例。


其他一些注意事项

  • 存储库和工作单元都不应该暴露给控制器。它们是负责处理存储的结构。您最终会将模型层的内部细节暴露给表示层。基本上,您的抽象正在泄漏

  • 我会小心阅读该教程。看来这篇文章的作者并没有完全掌握 DI 的概念。如果你看一下这段代码:

    public class SqlUnitOfWork : IUnitOfWork {
        public SqlUnitOfWork() {
            var connectionString =
                ConfigurationManager
                    .ConnectionStrings[ConnectionStringName]
                    .ConnectionString;
            _context = new ObjectContext(connectionString);
        }
    
        /* --- SNIP --- */
    
        readonly ObjectContext _context;
        const string ConnectionStringName = "EmployeeDataModelContainer";
    }
    

    您可以看到 DB 连接在构造函数中基于常量进行初始化,该常量已在SqlUnitOfWork类的定义中硬连线。这是一个非常糟糕的做法。

  • 如果您想了解更多关于 OOP 实践的依赖注入的一般信息,我建议您观看本讲座和同一系列的讲座。

于 2012-09-24T23:20:16.543 回答
0

您担心注入昂贵的创建对象是正确的。

依赖注入依赖于能够廉价地创建和注入对象(其中一些可能永远不会使用)。这就是为什么在构造函数中或在构建对象图时执行“实际工作”是一个坏主意的原因。

这里的问题是IRepository创建成本很高。如果它在构造函数中做“真正的工作”,你可以稍后将这项工作移到需要它之前吗?这有点像懒惰的评估。这解决了问题的根本原因。

有时,这是不可能的。有解决方法:

  • 注入一些东西,会给你一个 IRepository 的实例(一个工厂)
  • 将 IRepository 接口实现为 LazyRepository。LazyRepository 有一个真实的、昂贵的创建存储库的成员变量。在每种方法中,您检查此变量是否为空。如果是,则创建真正的存储库。然后,每个方法都委托给真正的存储库。
于 2012-09-24T23:09:17.797 回答
0

为昂贵的依赖注入工厂意味着该依赖的使用者知道依赖的接口有一个昂贵的实现。如果消费者相应地改变了它的实现,那就是一个泄漏的抽象。

看看这篇博文。它展示了如何使用 Unity 生成一个实时实现存储库接口的惰性代理。

根据这个线程,温莎城堡可以做同样的事情。

于 2012-09-25T07:04:57.647 回答