依赖注入与分层体系结构
本文关键字:体系结构 分层 注入 依赖 | 更新日期: 2023-09-27 18:25:14
我读了很多关于依赖注入和服务定位器(anti-?)模式的文章,其中很多都是关于StackOverflow的(谢谢大家:)。我有一个问题,当这个模式在n层架构中时,它是如何工作的。
我看过很多博客文章,其中描述了将IDataAccess组件注入业务对象。例如
public class Address
{
IDataAccess _dataAccess;
public Address(IDataAccess dataAccess)
{
this._dataAccess = dataAccess;
}
}
然而,我的印象是,在n层架构中,UI层不需要对数据访问层有任何了解。。。甚至知道有数据访问层!如果DI要求在BusinessObjects的构造函数中公开IDataAccess接口,那么这将向UI公开业务层在后台使用数据访问层这一事实——UI肯定不需要知道或关心这一点吗?
所以,我的基本问题是:DI是否要求我向所有上层公开所有下层接口,这是好事还是坏事?
感谢
编辑:为了澄清(在几条评论之后),我知道我的业务对象应该不知道它使用的IDataAccess的哪个特定的实现(因此在构造函数中注入了依赖项),但我认为BO之上的层不应该知道业务对象甚至需要对DAL的依赖项。
这确实是一个相当复杂的主题,有很多方法可以实现n层架构。没有一种方式是"正确的方式",你如何做到这一点取决于你的需求,也取决于你个人的偏好。
依赖项注入是关于管理依赖项的。如果您的对象不知道任何依赖关系,那么您就不会按照您提到的方式编写对象。相反,您将拥有一些其他服务或方法,这些服务或方法将以不可知的方式填充数据。数据也不意味着"数据库"。所以IDataAccess可能意味着它来自数据库,或者来自网络套接字,或者来自磁盘上的文件。这里的重点是Address不会选择它创建的依赖项。这是通过组合根目录下的配置完成的。
事情需要数据,否则你的应用程序可能毫无用处。然而,让Address对象自己加载可能不是处理事情的最佳方式。更好的方法可能是使用工厂类或服务方法。
我认为答案相当简单。底层(接口、bll、dal、实体)只是一堆libraries
。由客户决定使用哪些库,这将增加客户的灵活性。此外,它们是库,因此任何与应用程序相关的配置(连接字符串、数据缓存等)都位于客户端。这些配置本身,有时也需要注入并包含在CompositionRoot中。
但是,如果您想要uniform logic
而不是客户端的灵活性,则可以选择web/应用程序服务作为附加层。
1st Layer Entities
2nd Layer Interface
3rd Layer BLL & DAL
4th Layer Web/App Services
5th Layer UI
这样,你的作文根就存在于一层(第四层)。添加UI只需要将服务引用添加到第4层(如果需要,则添加到第1层)。然而,这再次暗示了Mark Seeman的文章,分层是值得映射的。我认为您可以将app/web service
更改为Composition Root
。
此外,这种(应用程序/网络服务)设计也有利弊。优点:
您的应用程序已封装
您的应用程序正在通过应用程序/web服务进行桥接。保证您的UI不知道
DataAccess
,从而满足您的要求。你的应用程序是安全的
简单地说,用户界面需要访问应用程序服务,这在安全方面是一个巨大的收获。
访问可移植性
现在,您的应用程序可以随时随地访问。它可以通过第三方应用程序(其他网络)连接,而无需依赖dll。
缺点:
服务呼叫期间的间接费用
身份验证、网络连接等会在Web服务调用过程中造成开销。我对性能影响没有经验,但对于高流量应用程序来说应该足够了。
客户端不灵活
客户端现在需要使用服务而不是普通对象来访问BLL/服务。
为不同类型的客户端提供更多服务
现在,您需要提供比所需更多的服务。如
WebRequestRetriever
、MobileRequestRetriever
而不是访问一个单纯的IRequestRetriever
,并让组成根线连接其余部分
如果这个答案超出了主题,请道歉(完成后才意识到)。
IMHO:
这取决于谁注射!-
你似乎需要/期望有一个MVC或MVP架构,其中控制器或演示者负责将UI调用来回转换为业务对象创建IDataAccess的具体实现,将其发送到Address类。这样UI就完全不知道是谁在提供它需要的数据,并且它为您提供了预期的可伸缩性。
谢谢Tarriq