一般 IoC 实践 - 服务相互依赖是错误的吗?

发布于 2025-01-05 03:14:00 字数 807 浏览 1 评论 0原文

现在,我有一些在不依赖于 IoC 容器(在我的例子中是 Ninject)的程序集中定义的服务。在主项目中,我有一个用于在容器中注册的数据访问的 IRepository。

this.Bind<IRepository>().To<EntityFrameworkRepository<MyDatabaseEntities>>();

我还注册了 IAuthenticationService 和 IErrorLogger 服务,我想将其具体实现用于其逻辑的存储库。但是,我不确定如何最好地实现这一点。目前,我在两个具体实现上的构造函数都采用 IRepository 参数,并在注册它们时将其传入:

this.Bind<IAuthenticationService>().To<MyAuthenticationService>().
                WithConstructorArgument("myRepository", ctx => ctx.Kernel.Get<IRepository());

这里我只是告诉容器获取 IRepository 实例并将其传递给构造函数。

我觉得让我的服务程序集依赖于 ninject 甚至公共服务定位器 (CSL) 是不对的,但我也不确定我当前的方式。我正在寻找意见和替代解决方案。

如果我的其他服务不使用 IRepository,我将必须为每种类型的底层 IRepository 类型创建这些服务的新的具体实现(例如,用于假数据和真实数据的 AuthenticationService)。这将是很多逻辑重复。

Right now I have a few services that are defined in an assembly that is not dependent on an IoC container (Ninject in my case). In the main project I have an IRepository for data access registered in the container.

this.Bind<IRepository>().To<EntityFrameworkRepository<MyDatabaseEntities>>();

I also have IAuthenticationService and IErrorLogger services registered, whose concrete implementation I want to use the repository for their logic. However, I am not sure how to best accomplish this. Currently, my constructor on both concrete implementations take an IRepository parameter and I pass it in when I register them:

this.Bind<IAuthenticationService>().To<MyAuthenticationService>().
                WithConstructorArgument("myRepository", ctx => ctx.Kernel.Get<IRepository());

Here I just tell the container to grab the IRepository instance and pass it to the constructor.

I didn't feel right about making my service assembly depend on ninject or even the common service locator (CSL), but I am not sure about my current way either. I am looking for opinions and alternate solutions.

If my other services don't use an IRepository, I would have to create new concrete implementations of these services for each type of underlying IRepository type (e.g. an AuthenticationService for both fake and real data). It would be a lot of logic repetition.

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

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

发布评论

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

评论(1

若能看破又如何 2025-01-12 03:14:00

您的服务程序集不应依赖于 Ninject,而应仅依赖于您注册具体类型的接口。 IoC 容器应该只是将依赖项注入到类中的聚合根。另一方面,包含聚合根/Ninject 内核的程序集将依赖于包含具体类型的所有程序集(否则它如何能够解析它们?)。

一般来说,对于 IoC,您应该在此处应用好莱坞原则 - 您应该为具体对象实例提供依赖项(如果可能的话,使用构造函数注入),而不是让对象实例询问其依赖项。

您用于 WithConstructorArgument() 的示例实际上根本不需要,因为依赖项解析以递归方式工作:您已经注册了 IRepositoryIAuthenticationService与容器一起,所以它知道如何解决这两个问题。由于 IAuthenticationService 绑定到 AuthenticationService,因此您无需指定构造函数参数,因为它的类型为 IRepository 并且会自动解析。

至于重复 - 当然,假设您希望这些存储库有不同的行为,您将必须为不同存储库类型的 IRepository 创建不同的实现

Your service assembly should not depend on Ninject, only on the interfaces that you register your concrete types for. The IoC container should be only the aggregate root to inject dependencies into your classes. The assembly that contains the aggregate root / the Ninject kernel on the other hand will depend on all of the assemblies that contain the concrete types (how else would it be able to resolve them?).

In general with IoC you should apply the Hollywood principle here - you should give the dependencies to your concrete object instances (using constructor injection if at all possible), not let the object instances ask for their dependencies.

The example you use for WithConstructorArgument() should not be needed at all actually, since dependency resolution works recursively: You have registered both IRepository and IAuthenticationService with the container, so it knows how to resolve both. Because IAuthenticationService is bound to AuthenticationServiceyou do not need to specify the constructor argument since it is of type IRepository and will be resolved automatically.

As to the repetition - of course you will have to create different implementations for IRepository for different repository types assuming you want different behavior of these repositories.

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