1

我是一名申请 ASP.NET 工作的 PHP 程序员。他们给了我一个任务,让我制作一个(我选择的)实现多层架构的应用程序。

我有很多难题。据我了解,多层是一个没有通用形式的概念,每个人都应该决定什么是最适合他们的。但是,他们建议我表示层不应该对数据访问层有任何引用,这是有道理的。但...

我创建了一个新项目Add new project(具有控制器和视图),它是一个表示层。现在,在表示层中,还有一个class library使用 Ninject 为整个应用程序注入依赖项的NinjectIoC. NinjectIoC 必须具有对表示层项目的引用,以便将依赖项作为参数直接注入控制器中。它还必须具有对所有其他层(DataAcessLayer、BusinessLayer 等)的引用,以便将它们绑定到它们的依赖项。

主要问题是表示层项目还必须具有对 NinjectIoC 的引用才能在 Global.asax 中创建 StandardKernel,这会创建循环依赖,并且是不允许的。

唯一的解决方案是添加对所有层(包括 DataAccessLayer)的表示层项目的引用,据我所知,这是一件坏事。但是,这是绑定所有层的所有接口并在 Global.asax 中执行的唯一方法。

我想错了吗?

编辑:

NinjectIoC安装了 Ninject 并引用了所有层,以便在应用程序中绑定它们。它必须具有对 UI 的引用才能在 Global.asax 中调用

UI 必须有一个引用,NinjectIoC以便它可以在 Global.asax 中调用它以进行控制器绑定。

我试图创建一个引用 NinjectIoC 的中间类库。UI 中引用了该库。问题是这也创建了一个循环依赖,因为 NinjectIoC 必须具有 UI 的引用才能绑定控制器。

4

1 回答 1

1

多层可以简单地表示有一个 DAL、一个 BL 和一个 UI 层。而“在 UI 层中不引用 DAL”的要求可能只是意味着您的 UI 层(MVC4 应用程序)只能引用 BL。这很容易实现,例如这样:

  • UI 项目 (MVC4)
  • 一个实体项目(类库):在这里定义使用的实体,并从所有必要的层引用它(这有助于避免循环引用)
  • 一个 BL 项目(类库):这必须引用实体和 DAL 项目
  • DAL 项目(类库):这引用了实体项目

这是经典的、最简单的、多层次的项目。

在最终的编译中,当然间接依赖会包括UI工程和3个库,但是不需要在UI中添加对DAL的引用。

另一个不同的问题是使用 IoC 模式。在这种情况下,为了解决循环引用问题,我建议您为每一层分别定义“接口”项目和“实现”项目。类似于以前的结构,但有以下变化:

  • 一个 UI 项目
  • 一个实体项目
  • 一个 BL 接口项目
  • 一个实现 BL 接口的项目
  • DAL 接口项目
  • 实现 DAL 接口的项目

您需要定义哪个是主要项目。它通常是 UI 项目。该项目将具有所有依赖项。

在这种情况下,UI 项目直接依赖于 BL Interfaces 项目。BL 接口将依赖于 DAL 接口。简而言之,您的 UI 项目将仅直接依赖于 BL 接口。

问题是,当你尝试运行代码时,它需要解决这个依赖关系,即找到接口的实现,以及存在依赖关系。这是应用程序的“组合根”,也是您需要注册依赖项的地方。即,这是您需要定义每个接口将使用哪个具体实现的地方。而且,如果此实现依赖于其他接口,您还必须定义它们的实现。根据框架(我不知道您是否可以使用 NInject 来实现),您可以动态地执行此操作,而无需添加对实现项目的引用。但是,即使您必须包含对所有其他实现和接口项目的引用,您也没有循环依赖,并且您的 UI 将不依赖于 DAL 或实现层。您只需要它们在 IoC 容器中注册它们,这是一个非常不同的问题。(如果您使用构造函数注入,则使用此项目结构可以获得最大可能的解耦)。

保留一个或多个单独的实体项目可以避免循环引用和项目之间的直接依赖关系。例如,如果您在 DAL 项目中定义了实体,那么在您的 UI 项目中使用它们时,您需要添加对 DAL 项目的引用。如果实体在单独的项目中声明,这个问题就会消失。

纯粹的IoC,如“洋葱架构”,远不止于此,它在主项目(UI项目)中定义依赖的实体和必要的接口,然后在其他项目中实现这些依赖,并动态解决它们,避免循环引用。即所有其他项目直接或间接依赖于 UI 项目,而不是相反。在这种情况下,您需要动态解决依赖关系以避免循环引用。

如您所见,有很多选择,我已经向您展示了几个可行的解决方案示例。

于 2014-12-17T15:12:35.897 回答