如何在多层解决方案中正确使用 StructureMap(或任何其他 IoC 容器)?

How can I correctly use StructureMap (or any other IoC container) on a multi layered solution?

我有一个具有以下结构的 3 层解决方案:

UI -> BLL <- DAL

UI 是一个 ASP.NET MVC 应用程序。每个控制器都需要在其构造函数上使用 BLL 组件。并且每个 BLL 组件都需要在其构造函数上使用 DAL 组件。

以前我用StructureMap作为IoC容器。在其早期版本中,StructureMap 使用静态的 ObjectFactory class。因为它是静态的 class 我可以在 MVC 上使用 StructureMap 来替换默认的 ControllerFactory 然后是另一个进行了 BLL 和 DAL 配置的项目。

在较新的 StructureMap 版本中,ObjectFactory 已被标记为过时。我明白现在我必须提供我自己的 Container 实例。

但是,如果没有连接我的项目,我就不会发生这种连锁反应。此外,如果我将配置添加到 BLL 和 DAL 到 MVC 项目,我将不得不引用我想避免的 UI 级别的所有内容。

我想我要做的是用 StructureMap 保留两个不同的项目。

MVC项目内部的一个,负责创建controller。但是,我需要找出一种方法将 BLL 实例委托给第二个容器,它可能会保持原样并且知道如何创建 BLL 和 DAL(因此可以创建 BLL)。

第二个(创建 BLL 组件)如下所示:

public static class BLLContainer
{
    public static Container BuildServiceContainer()
    {
        return new Container(x =>
        {
            // This uses the Scan method to locate BLL and DAL
            // interfaces and implementations.
            x.AddRegistry(new DALRegistry());
        });
    }
}

我的问题是:

  1. 是否真的可以在 BLL 级别将对象创建从我的 MVC 应用程序委托给 StructureMap 容器,而无需引用其他(不需要的)项目?

  2. 如果我返回容器的新实例,如上面的代码所示,这意味着我是 运行 对 Web 服务器的每个请求的扫描器(StructureMap 使用 PerRequest作为默认值)。我怎样才能避免这种情况?除了回到单身人士之外,我看不出如何防止这种情况发生。

我从未使用过 StructureMap,因此我的回答与 StructureMap 或如何使用它无关。

当你使用依赖注入时,一切都围绕着你的 composition root。这是组成完整应用程序的地方,所以这个地方也需要您的应用程序的完整知识。

如果您真的不想从 UI 引用您的 DAL,您可以将您的组合根目录放在不同的程序集中,并从您的 UI 程序集中引用该程序集。

但这有什么区别呢?通过从 UI 引用 BL 和 DAL 程序集,你 I.M.O. 没有做错任何事情,只要你仅从组合根而不是 DAL 中引用 类直接在您的控制器中使用它们。除了造成错误执行该操作的可能性之外,没有其他真正的问题。

关于你的第二个问题。您的应用程序必须有 1 个且只有 1 个 DI 容器。将其拆分到多个容器中会给您带来麻烦。已经提到的 Mark Seeman 的博客明确指出每个应用程序都需要一个单一的组合根。

一个体面的 DI 容器将为您提供各种选项来控制所创建对象的生命周期,因此只要您给容器提供这样做的机会,所有单例都不是必需的。

我选择的 DI 容器是 Simple Injector. You can start reading about this container here. Simple Injector also has a quick start package for MVC,它有非常热情的社区,随时乐意为您提供帮助。