开发者

Can dependency injection prevent a circular dependency?

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?


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.


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜