如何在多层解决方案中正确使用 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());
});
}
}
我的问题是:
是否真的可以在 BLL 级别将对象创建从我的 MVC 应用程序委托给 StructureMap 容器,而无需引用其他(不需要的)项目?
如果我返回容器的新实例,如上面的代码所示,这意味着我是 运行 对 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,它有非常热情的社区,随时乐意为您提供帮助。
我有一个具有以下结构的 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());
});
}
}
我的问题是:
是否真的可以在 BLL 级别将对象创建从我的 MVC 应用程序委托给 StructureMap 容器,而无需引用其他(不需要的)项目?
如果我返回容器的新实例,如上面的代码所示,这意味着我是 运行 对 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,它有非常热情的社区,随时乐意为您提供帮助。