3

我一直在阅读很多关于依赖注入和服务定位器(反?)模式的内容——很多都在 StackOverflow 上(谢谢大家:)。我有一个关于这种模式在 n 层架构中如何工作的问题。

我看过很多博客文章,其中描述了将 IDataAccess 组件注入业务对象。例如

public class Address
{
    IDataAccess _dataAccess;
    public Address(IDataAccess dataAccess)
    {
        this._dataAccess = dataAccess;
    }
}

但是,我的印象是,在 n 层架构中,UI 层应该不需要任何数据访问层的知识……甚至不需要知道 /is/ 有数据访问层!如果 DI 需要在 BusinessObjects 的构造函数中公开 IDataAccess 接口,那么这会向 UI 公开业务层在后台使用数据访问层的事实——这是 UI 不需要知道或关心的事情吗?

所以,我的基本问题是:DI 是否要求我将所有下层接口暴露给所有上层,这是好事还是坏事?

谢谢

编辑:为了澄清(经过几条评论),我知道我的业务对象应该不知道它使用哪个 IDataAccess 的具体实现(因此在构造函数中注入了依赖项),但我认为 BO 上方的层不应该知道业务对象甚至需要对 DAL 的依赖。

4

3 回答 3

2

这确实是一个相当复杂的话题,并且有很多方法可以实现 n 层架构。没有一种方法是“正确的方法”,你如何做取决于你的需求和你的个人喜好。

依赖注入是关于管理依赖的。如果您的对象不知道任何依赖关系,那么您就不会按照您提到的方式编写您的对象。相反,您将拥有一些其他服务或方法,这些服务或方法将以不可知的方式填充数据。数据也不意味着“数据库”。所以 IDataAccess 可能意味着它来自数据库,或者来自网络套接字,或者来自磁盘上的文件。这里的重点是 Address 不选择它创建的依赖项。这是通过组合根的配置来完成的。

事物需要数据,否则您的应用程序可能毫无用处。然而,让你的 Address 对象自己加载可能不是最好的方法。更好的方法可能是使用工厂类或服务方法。

于 2013-07-29T09:11:07.683 回答
1

我认为答案相当简单。您的底层(接口、bll、dal、实体)只是一堆libraries. 由客户决定使用哪些库,这将增加客户的灵活性。此外,它们是库,因此任何与应用程序相关的配置(连接字符串、数据缓存等)都位于客户端上。这些配置本身,有时也需要注入并包含在 Composition Root 中。

但是,如果您想要拥有uniform logic而不是客户端的灵活性,您可以选择 web/app 服务作为附加层。

1st Layer        Entities

2nd Layer       Interface

3rd Layer       BLL  &  DAL

4th Layer    Web/App Services

5th Layer           UI

这样,您的组合根存在于一层(第 4 层)中。添加您的 UI 只需将服务引用添加到第 4 层(或第 1 层,如果需要)。然而,这又暗示了同样的 Mark Seeman 的文章,分层值得映射。我假设您可以app/web serviceComposition Root.

此外,这种(应用程序/网络服务)设计有利有弊。优点:

  1. 您的应用已封装

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

  2. 您的应用是安全的

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

  3. 访问便携性

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

缺点:

  1. 服务呼叫期间的间接费用

    身份验证、网络连接等会在 webservice 调用过程中造成开销。我对性能影响没有经验,但对于高流量应用程序来说应该足够了。

  2. 客户不灵活

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

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

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

如果这个答案引起了话题,请道歉(完成后才意识到)。

于 2013-07-29T11:46:15.277 回答
0

恕我直言:

这取决于谁注射!-

您似乎需要/期望有一个 MVC 或 MVP 架构,其中控制器或演示者负责将 UI 调用来回转换为业务对象 - 创建 IDataAccess 的具体实现,将其发送到地址班级。这样 UI 就完全不知道谁在提供它需要的数据,它为您提供了预期的可伸缩性。

谢谢塔里克

于 2013-07-29T16:31:53.720 回答