Fluent IOC 配置/模块的最佳位置(当前正在尝试 Ninject)

发布于 2024-11-02 16:27:59 字数 615 浏览 6 评论 0原文

我正在努力寻找放置 Ninject 配置“模块”的最佳位置(指定类型绑定的位置)。我希望我只是错过了一些明显的技巧,因为这开始成为我使用流畅配置(以及 Ninject)的一个障碍:

在一个包含三个独立项目的简单 Web 堆栈中:Web、BusinessLogic、DataAccess。我不希望 Web 层必须直接引用 DataAccess 层,但我找不到解决此问题的方法,因为:

  • 如果我将 DataAccess 配置模块放在DataAccess层,我必须引用DataAccess层,以便在Web层实例化Ninject Kernel时可以访问配置模块

  • 如果我将DataAccess 配置模块放在 Web 层,我必须引用 DataAccess 层才能访问到我想要绑定的类型

  • 如果我把DataAccess 配置模块位于单独的配置项目中,当我尝试指定 Web 层和 DataAccess 层的绑定时,我最终会遇到循环引用问题。

IOC 的部分好处是允许松散耦合,但据我所知,使用 Ninject 需要我添加目前拥有的更多直接项目引用。我缺少什么?

I am struggling to find the best place to locate my Ninject configuration "Modules" (the place where Type bindings are specified). I hope I am just missing some obvious trick, as this is starting to turn into a deal-breaker for me with using fluent configuration (and thus Ninject):

In a simple Web stack containing three separate projects: Web, BusinessLogic, DataAccess. I do not want the Web tier to have to directly reference the DataAccess tier, but I can't see a way around this because:

  • If I put the DataAccess configuration Module in the DataAccess layer, I have to reference DataAccess layer so I can access the configuration module when instantiating the Ninject Kernel in the Web tier

  • If I put the DataAccess configuration Module in the Web tier, I have to reference the DataAccess layer to have access to the types I want to bind

  • If I put the DataAccess configuration Module in a separate configuration project, I end up with circular reference issues when trying to specify bindings for both web and DataAccess tiers.

Part of the benefit of IOC is to allow loose coupling, but as far as I can see, use of Ninject would require me to add more direct project references that I currently have. What am I missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

半衬遮猫 2024-11-09 16:27:59

Ninject 不要求引用程序集!您可以告诉内核从与特定模式匹配的程序集中加载所有模块 - 请参阅Load() 重载!使用这种机制,您可以将功能公开为模块,正如 @Daniel Marbach 在实现每个功能的地方所建议的那样。我不喜欢这些巨大的模块定义程序集的每个绑定。我宁愿将每个模块都放在一个特定的小模块中以实现特定的功能。

这还允许人们启用/禁用/替换实现,而无需重新编译其他程序集(至少在您的接口位于单独的程序集中的情况下)。

所以基本上你有:

  • 一个或多个 Web 层程序集:包含 Web 层的控制器、视图和绑定。每个程序集都引用一些定义它所依赖的接口的程序集。
  • 定义 Web 层依赖项的接口的一个或多个程序集。
  • 一个或多个业务逻辑程序集实现 Web 层所需的全部或部分接口。引用一些包含它们所依赖的对象的接口的程序集。包含定义它们提供的组件的绑定的模块。
  • 定义业务逻辑层依赖项的接口的一个或多个程序集。
  • 一个或多个程序集,用于实现业务逻辑层以及可能的某些 Web 层(例如,直接提供的数据而不涉及业务逻辑)的依赖关系。包含他们提供的组件的模块。
  • 一个引导程序使用 kernel.Load("*.dll") 或类似方法加载这些程序集的模块。

这样做的好处是:

  • Web 层没有对业务逻辑层和数据层的引用
  • 业务逻辑层没有对数据层的引用
  • 每层都是可替换的,不会对其他层产生任何影响

Ninject does not require that the assemblies are referenced! You can tell the Kernel to load all modules from the assemblies that match a certain pattern - see the Load() overloads! Using this mechanism you map the can expose your features as Modules as @Daniel Marbach suggested in the place where each feature is implemented. I do not like these huge modules defining every binding for an assembly. I'd rather have each in a specific small module for a certain feature.

This also allows one to enable/disable/replace implementations without recompilation of the other assemblies (at least in case you have the interfaces in separate assemblies).

So basically you have:

  • One or more web tier assemblies: containing the controllers, views and bindings for the web tier. Each of the assembly references some assemblies that define the interfaces it depends on.
  • One or more assemblies that define the interfaces for the dependencies of the web tier.
  • One or more business logic assemblies implementing all or some of the interfaces required by the web tier. Referencing some assemblies that contain the interfaces of the objects they depend on. Containing the modules that define the bindings for the components they provide.
  • One or more assemblies that define the interfaces for the dependencies of the business logic tier.
  • One or more assemblies that implement the the dependencies of the business logic tier and possibly some of the web tier (e.g. data that is directly provided with out the business logic). Containing the modules of the components they provide.
  • One bootstrapper loading the modules of these assemblies using kernel.Load("*.dll") or similar.

The advantage of this is:

  • No reference from the web tier to the business logic tier and data tier
  • No reference from the business logic tier to the data tier
  • Each layer is replaceable without any impact on the others
鸠书 2024-11-09 16:27:59

我通常只为 IOC 容器和配置创建一个程序集;然后,该程序集可以引用所有其他程序集和 Ninject(或在我的例子中为 StructureMap)。然后,Web 应用程序只需引用 IOC 程序集并包含几行直接使用 IOC 程序集的初始化代码。

但需要注意的是 - 我的 IOC 程序集不引用 Web 程序集(这会引入循环引用)。任何需要注入的东西都是在 Web 程序集之外定义的,所以这不是我关心的问题。

I typically create an assembly just for the IOC Container and configuration; That Assembly can then reference all of the other Assemblies and Ninject (or StructureMap in my case). Then the web application just has to reference the IOC assembly and include a couple lines of initialization code that directly use the IOC assembly.

One note however - My IOC assembly does not reference the web assembly (that would introduce a circular reference). Anything that needs to be injected is defined outside of the web assembly, so this is not a concern for me.

舞袖。长 2024-11-09 16:27:59

组织模块的最佳方式是按功能!例如

  • AuthenticationModule
  • OrderModule
  • CustomerModule

玩得开心!

The best way to organize your modules is by feature! For example

  • AuthenticationModule
  • OrderModule
  • CustomerModule

Have fun!

森末i 2024-11-09 16:27:59

我总是将 Ninject 模块配置放入单独的程序集中,例如 Acme.Common,并从 Acme.Data、Acme.Domain 等引用此程序集,因此不存在循环依赖关系,在注册中进行一些修改后,我始终可以轻松替换 Acme.Common。

I always put Ninject Modules Configuration into separate assembly like Acme.Common and reference to this from Acme.Data, Acme.Domain etc. so there is no circular dependencies, I can always replace Acme.Common after some modifications in registrations without troubles.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文