views:

335

answers:

3

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?

+1  A: 

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.

jdmichal
+1  A: 

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.

Mark Seemann
+5  A: 

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 ->--------------------->-------------------|
  
  1. 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.

Aaronaught
You were write, I was trying to instantiate the concrete class directly in AssemblyA, I just needed to reference the interface. The web project now instantiates the concrete, and passes it to AssemblyA as a parameter (the parameter is the interface). thanks allot!
mrblah