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