gpt4 book ai didi

dependency-injection - 如何在 n 层应用程序中使用 MVC5 和 MEF2(基于约定)实现依赖注入(inject)?

转载 作者:行者123 更新时间:2023-12-02 20:39:01 25 4
gpt4 key购买 nike

我正在开始一个新的 MVC 项目,并且(几乎)决定尝试一下 Repository Pattern 和 Dependency Injection。筛选变化需要一段时间,但我为我的应用程序提出了以下结构:

  • 表示层:ASP.Net MVC 前端( View / Controller 等)
  • 服务层(业务层,如果您愿意):接口(interface)和 DTO。
  • 数据层:接口(interface)实现和 Entity Framework 类。

  • 在我的解决方案中,它们是 3 个独立的项目。表示层只有对服务层的引用。数据层也只有对服务层的引用——所以这基本上遵循领域驱动设计。

    以这种方式构建事物的目的是为了关注点分离、松散耦合和可测试性。如果其中任何一项不合理,我很乐意就改进提出建议?

    我遇到困难的部分是将接口(interface)实现对象从数据层注入(inject)到表示层,它只知道服务层中的接口(interface)。这似乎正是 DI 的用途,而 IoC 框架(据称!)使这更容易,所以我想我会尝试 MEF2。但是在过去几天我阅读的数十篇文章和问题和答案中,似乎没有什么能以适合我结构的方式真正解决这个问题。几乎所有这些都已弃用和/或都是简单的控制台应用程序示例,它们在同一个程序集中具有所有接口(interface)和类,彼此了解,完全无视松散耦合和 DI 的观点。我还看到其他需要将数据层 dll 放入表示层 bin 文件夹并配置其他类以查看那里的其他类 - 再次阻碍了松散耦合的想法。

    有一些解决方案探索基于属性的注册,但据说已经被基于约定的注册所取代。我还看到很多将对象注入(inject) Controller 构造函数的示例,这引入了它自己要解决的一组问题。我不相信 Controller 实际上应该知道这一点,并且宁愿将对象注入(inject)模型中,但这可能是有原因的,因为很多示例似乎都遵循这条路径。我还没有深入研究这一点,因为我仍然坚持尝试将数据层对象放到任何地方的表示层中。

    我相信我的主要问题之一是不了解各种 MEF2 需要在哪一层进行,因为我发现的每个示例都只使用一层。有容器、注册和目录以及导出和导入配置,我一直无法弄清楚所有这些代码应该放在哪里。

    具有讽刺意味的是,现代设计模式本应抽象复杂性并简化我们的任务,但如果我刚刚从 PL 中引用 DAL 并着手处理应用程序的实际功能,我现在已经完成了一半。如果有人能说,‘是的,我明白你在做什么,但你缺少 xyz,我会非常感激。你需要做的是 abc'。

    谢谢。

    最佳答案

    是的,我明白你在做什么(或多或少)但是(据我所知)你错过了 a)将契约(Contract)和实现类型分离到他们自己的项目/程序集中和 b)配置的概念DI 容器,即配置哪些实现应用于接口(interface)。

    有无限的方法来处理这个问题,所以我给你的是我个人的最佳实践。我已经用这种方式工作了很长时间,并且仍然对它感到满意,所以我认为它值得分享。

    一种。总是有项目:MyNamespace.SomethingMyNamespace.Something.Contracts

    一般来说,对于 DI,我有两个程序集:一个用于仅包含接口(interface)的合约,另一个用于实现这些接口(interface)。在您的情况下,我可能有五个程序集:Presentation.dll , Services.dll , Services.Contracts.dll , DataAccess.dllDataAccess.Contracts.dll .

    (另一个有效的选择是将所有契约(Contract)放在一个程序集中,我们称之为 Commons.dll)

    显然,DataAccess.dll引用资料 DataAccess.Contracts.dll , 作为 DataAccess.dll 中的类实现 DataAccess.Contracts.dll 内部的接口(interface). Services.dll 相同和 Services.Contracts.dll .

    不,去耦部分:Presentation引用资料 Services.ContractsData.Contracts .服务引用 Data.Contracts .如您所见,不依赖于具体的实现。这就是整个 DI 的内容。如果你决定交换你的数据访问层,你可以交换 DataAccess.dllDataAccess.Contracts.dll保持不变。您的其他程序集都没有直接引用DataAccess.dll,因此没有断开的链接,版本冲突等。如果不清楚,请尝试绘制一点依赖关系图。您会看到,没有箭头指向任何没有 .Contracts 的程序集。以他们的名义。

    你能理解这个吗?请问有什么不清楚的地方。

    湾。选择如何配置容器

    您可以在显式配置(XML 等)、基于属性的配置和基于约定的注册之间进行选择。虽然出于显而易见的原因前者很痛苦,但我是后者的粉丝。我认为它比基于约定的配置更具可读性和易于调试,但这是一个品味问题。

    当然,容器类型捆绑了所有依赖项,而您在应用程序架构中已经避免了这些依赖项。为了明确我的意思,请考虑针对您的案例的 XML 配置:它将包含到所有实现程序集的“链接”DataAccess.dll, ... .尽管如此,这并没有破坏脱钩的想法。很明显,当交换实现程序集时,您需要修改配置。

    但是,使用基于属性或约定的配置时,您通常使用您提到的自动发现机制:“在位于 xyz 的所有程序集中搜索”。这确实需要将所有程序集放在应用程序 bin 目录中。它没有任何问题,因为代码需要在某个地方,对吧?

    你有什么收获?假设您已经部署了应用程序并决定交换 DataAccess 层。假设您选择了基于约定的 DI 容器配置。你现在可以做的是在VS中打开一个新项目,引用现有的DataAccess.Contracts.dll并以任何你喜欢的方式实现所有接口(interface),只要你遵循约定。然后构建库,将其命名为 DataAccess.dll并将其复制并粘贴到原始应用程序的程序文件夹中,替换旧的 DataAccess.dll .完成后,您已经交换了整个实现,甚至没有注意到任何其他程序集。

    我想你应该已经明白了。这确实是一个权衡,使用 IoC 和 DI。我强烈建议您在设计决策时要务实。不要接口(interface)所有东西,它只会变得困惑。自己决定,DI 和 IoC 真正有意义的地方,不要太受社区宗教讨论的影响。尽管如此,如果使用得当,IoC 和 DI 真的非常非常强大!

    关于dependency-injection - 如何在 n 层应用程序中使用 MVC5 和 MEF2(基于约定)实现依赖注入(inject)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24217142/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com