我是一名申请了ASP.NET工作的PHP程序员。他们给了我一个委托(我选择)实现多层arhitecuture的应用程序。
我有很多dillemas。据我所知,多层是一个没有通用形式的概念,每个人都应该决定什么是最适合他们的。然而,他们告诉我,表示层不应该对数据访问层有任何反馈,这是有道理的。但...
我使用Add new project
创建了一个新项目(具有控制器和视图),这是一个表示层。现在,在表示层中,还有一个class library
,它使用Ninject为名为NinjectIoC
的整个应用程序注入依赖项。 NinjectIoC必须对表示层项目进行引用,以便将依赖项直接注入控制器作为参数。它还必须对所有其他层(DataAcessLayer,BusinessLayer等...)进行引用,以便将它们绑定到它们的依赖项。
主要问题是表示层项目还必须对NinjectIoC进行参考,以在Global.asax中创建StandardKernel,这会产生一个cirucullar依赖,并且是不允许的。
唯一的解决方案是在所有层(包括DataAccessLayer)的表示层项目中添加一个引用,据我所知,这是一件坏事。但是,这是绑定所有层的所有接口并在Global.asax中执行它的唯一方法。
我认为错了吗?
编辑:
NinjectIoC
安装了Ninject并引用了所有图层,以便在整个应用程序中绑定它们。它必须具有对UI的引用才能在Global.asax中调用
UI必须引用NinjectIoC
,以便它可以在Global.asax中调用它来进行控制器绑定。
我尝试创建一个引用NinjectIoC的中间类库。该库在UI中引用。问题是,这也会产生循环依赖性,因为NinjectIoC必须具有UI的引用才能绑定控制器。
答案 0 :(得分:1)
多层可以简单地表示存在DAL,BL和UI层。并且要求"不要在UI层中引用DAL"可以简单地表示您的UI层(MVC4应用程序)只能引用BL。这很容易实现,例如:
这是经典,最简单,多层次的项目。
在最终编译中,当然,间接依赖项将包括UI项目和3个库,但您不需要在UI中添加对DAL的引用。
另一个不同的问题是使用IoC模式。在这种情况下,为了解决循环引用问题,我建议你单独定义"接口"和#34;实施"的项目对于每一层。与之前的结构类似的东西,但有了这些变化:
您需要定义哪个是主项目。它通常是UI项目。这个项目将具有所有依赖项。
在这种情况下,UI项目直接依赖于BL Interfaces项目。 BL接口将取决于DAL接口。简而言之,您的UI项目只与BL接口有直接的依赖关系。
问题是,当您尝试运行代码时,它将需要解决此依赖关系,即找到接口的实现,以及依赖关系。这是" compositio root"您的应用程序,以及您需要注册依赖项的位置。即,这是您需要定义每个接口将使用哪个具体实现的地方。而且,如果此实现依赖于其他接口,则还必须定义其实现。根据框架(我不知道您是否可以使用NInject),您可以动态执行此操作,而无需添加对实现项目的引用。但是,即使您必须包含对所有其他实现和接口项目的引用,您也没有循环依赖项,并且您的UI将不依赖于DAL或实现层。您只需要它们在IoC容器中注册它们,这是一个非常不同的问题。 (如果使用构造函数注入,则可以使用此项目结构获得最大可能的decopuling。)
保留一个或多个独立的实体项目允许您避免循环引用,并直接在项目之间进行依赖。例如,如果您在DAL项目中定义了实体,那么在UI项目中使用它们时,您需要添加对DAL项目的引用。如果在单独的项目中声明实体,则此问题会消失。
纯IoC,如" Onion Architecture"通过在主项目(UI项目)中定义依赖项的实体和必要接口,然后在其他项目中实现这些依赖项并动态解决它们来避免循环引用,远远超出了这个范围。即所有其他项目直接或间接依赖于UI项目,而不是相反。在这种情况下,您需要动态地解决依赖关系以避免循环引用。
正如您所看到的,有很多选择,我已经向您展示了几个工作解决方案的例子。