依赖注入与分层体系结构

时间:2013-07-29 08:58:59

标签: c# architecture dependency-injection

我一直在阅读很多关于依赖注入和服务定位器(反?)模式的内容 - 很多关于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。

3 个答案:

答案 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服务)设计有利弊。优点:

  1. 您的应用已封装

    您的应用正在通过应用/网络服务进行桥接。保证您的UI不知道DataAccess,从而满足您的要求。

  2. 您的应用已受到保护

    简单地说,让UI需要访问应用服务是安全方面的巨大收获。

  3. 访问可移植性

    现在您的应用可以随处访问。它可以通过第三方应用程序(其他网络)连接,而不依赖于dll。

  4. 缺点:

    1. 服务电话中的间接费用

      身份验证,网络连接等将在Web服务调用期间导致开销。我对性能影响缺乏经验,但对于高流量应用来说应该足够了。

    2. 客户缺乏灵活性

      客户现在需要使用服务而不是普通对象来访问BLL /服务。

    3. 为不同类型的客户提供更多服务

      现在您需要提供超出需要的服务。例如WebRequestRetrieverMobileRequestRetriever,而不是访问仅仅IRequestRetriever,并让组合根连接其余部分。

    4. 道歉,如果这个答案超过了主题(刚完成后才意识到)。

答案 2 :(得分:0)

IMHO:

这取决于谁注射! -

似乎你需要/期望有一个MVC或MVP架构,控制器或Presenter负责将UI调用转换为业务对象,来回 - 创建IDataAccess的具体实现,将其发送到Address类。 因此,用户界面完全不知道谁在提供所需的数据,并为您提供了预期的可扩展性。

由于 Tarriq