依赖注入可以防止循环依赖吗?

发布于 2024-08-17 19:36:44 字数 178 浏览 4 评论 0原文

项目#1 具有项目#2 引用的一些接口和类。

现在我想在 Project#1 中使用 Project#2 的实现,但 vs.net 抱怨循环依赖。

如果我要在 Project#1 中使用依赖注入并绑定到 Project#2 中的实现(因为它遵守接口契约),这是否有效,或者我仍然会在运行时收到循环依赖错误消息?

Project#1 has some interfaces and classes that project#2 references.

Now I want to use the implementation of Project#2 in Project#1 but vs.net complains about a circular dependency.

If I was to use dependancy injection in Project#1 and bind to the implementation in Project#2 (since it adheres to the interface contract), will this work or I will still get the circular dependency error message at runtime?

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

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

发布评论

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

评论(3

春庭雪 2024-08-24 19:36:44

您可能可以使用 DI 解决这个问题,但您不应该

如果我理解正确的话,你会得到这样的结果:

  + Assembly A           + Assembly B
  |                      |
  +-- Interface IFoo     +-- Class ConcreteFoo : IFoo
  |                                   ^
  +-- Class MyClass -->------->-------|

换句话说,你试图让 MyClass 引用 ConcreteFoo,但你不能,因为程序集 ConcreteFoo 所在的 B 已经依赖于 A 中的 IFoo

这是一个设计错误。如果您在程序集 A 中声明接口 IFoo,但没有具体实现,则程序集 A 中的任何其他接口/类应该引用IFoo从不实现它的具体类。

可以通过三种方法消除循环依赖:

  1. 使 MyClass 依赖于 IFoo 而不是 ConcreteFoo。如果你能做到的话,这可能是最好的选择。如果问题是您需要一个 IFoo 的物理实例以在 MyClass 中使用,并且不知道从哪里获取,那么让它采用一个 IFoo 在构造函数中 - 让使用 MyClass 的人弄清楚要使用什么 IFoo

  2. 将接口移动到它们自己的程序集中。这仍然是一个相当好的做法。您的设计将如下所示:

     + 装配应用程序 + 装配接口 + 装配混凝土
      | | |
      | +-- 接口 IFoo |
      | | \ |
      +-- 类 MyClass | \------+-- 类 ConcreteFoo
      | | | ^
      +---- Foo 会员 ->--------------------->----------------- --|
    
  3. MyClass 移动到其自己的程序集。实际上,您的依赖关系树看起来与上面#2 中的相同,但如果程序集 AB 小得多,那么这将需要更少的工作。

希望有帮助。

You probably could solve this with DI, but you shouldn't.

If I understand correctly, you have something like this:

  + Assembly A           + Assembly B
  |                      |
  +-- Interface IFoo     +-- Class ConcreteFoo : IFoo
  |                                   ^
  +-- Class MyClass -->------->-------|

In other words, you're trying to get MyClass to reference ConcreteFoo, but you can't because assembly B, which ConcreteFoo resides in, already depends on IFoo in A.

This is a design error. If you declare the interface IFoo in Assembly A, but no concrete implementations, then any other interfaces/classes in assembly A should only reference IFoo, never a concrete class that implements it.

There are three ways to eliminate the circular dependency:

  1. Make MyClass dependent on IFoo instead of ConcreteFoo. This is probably the best option if you can do it. If the issue is that you need a physical instance of IFoo for use in MyClass and don't know where to get one from, then have it take an IFoo in the constructor - let whoever uses MyClass figure out what IFoo to use.

  2. Move the interfaces to their own assembly. This is still a reasonably good practice. Your design will look like this:

      + Assembly App       + Assembly Interfaces      + Assembly Concrete
      |                    |                          |
      |                    +-- Interface IFoo         |
      |                    |                  \       |
      +-- Class MyClass    |                   \------+-- Class ConcreteFoo
      |                    |                          |           ^
      +---- Member Foo ->--------------------->-------------------|
    
  3. Move MyClass to its own assembly. Effectively your dependency tree will look the same as in #2 above, but if assembly A is much smaller than B then this would require less effort.

Hope that helps.

土豪 2024-08-24 19:36:44

您通常可以使用抽象工厂通过依赖注入 (DI) 解决循环依赖问题。请参阅这里是一个例子

然而,虽然你也许能够通过 DI 解决问题,但最好重新设计 API 以消除循环依赖。

您通常可以通过将一端从基于查询的 API 更改为基于事件 API 来打破循环依赖关系。

You can often resolve circular dependency issues with Dependency Injection (DI) using an Abstract Factory. See here for an example.

However, although you may be able to solve the problem with DI, it would be better to redesign the API to make the circular dependency go away.

You can often break a circular dependency by changing one of the ends from a query-based API to an event-based API.

染年凉城似染瑾 2024-08-24 19:36:44

只要您仅在项目 1 代码中使用项目 1 中的类和接口,就可以了。 (我假设依赖项注入的配置是在项目 1 的代码库之外完成的。)

但我还必须说,任何循环依赖项的存在都会导致您质疑它为什么存在,并提示您思考其他问题解决问题的方法,从而消除它。

As long as you are only using classes and interfaces from Project 1 in Project 1 code, you will be fine. (I'm assuming that the configuration for the dependency injection is done outside of the codebase of Project 1.)

But I have to also say, the presence of any circular dependency should lead you to question why it exists, and prompt thought on other ways to solve the problem that removes it.

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