views:

31

answers:

1

Here is the example code:

public interface IService<TEntity> {        
        IContext Context { get; set; }
        //unimportant methods
        bool Validate(TEntity entity);
        void Add(TEntity enttity);
    }

 public class UsersController : Controller {
        private IService<User> _service;
        public MyController(IService<User> service){
            _service = service;
            _service.Context = ControllerContext;
        }
    }

I'm using AutofacControllerFactory to create controllers in my ASP.NET MVC app. Is it possible to eliminate this line of code in every controller's constructor:

_service.Context = ControllerContext;

In other words: is it possible to automatically set this property with ControllerContext? It should be possible because every IService implementation has a settable IContext property.

Should I extend the AutofacControllerFactory or is there a standard way of doint this?

+1  A: 

What you have there is a Circular Dependency.

  • UsersController depends on IService<User>
  • IService<User> depends on ControllerContext
  • ControllerContext depends on UsersController

No DI Container can reach into your classes' innards and control what happens there. They can set up dependencies for you and inject them into your classes from the outside. However, they can't very well deal with circular dependencies, so a better option is to redesign the API.

From here it looks very much like the Context property of IService<TEntity> is a Leaky Abstraction. A Service shouldn't need to know anything about the UI framework in which it is running.

You can often break a circular dependency by changing one of the consumers to a more event-driven architecture.

Here's an article about this sort of problem.

Here's a related answer to a ASP.NET MVC question that looks a lot like yours: http://stackoverflow.com/questions/1453128/is-there-a-good-proper-way-of-solving-the-dependency-injection-loop-problem-in-th/1453242#1453242

See also the answer: http://stackoverflow.com/questions/2608875/bad-design-constructor-of-composition-uses-this/2616266#2616266

Mark Seemann
Mark, thanks for the answer. In my case the service is a UI coordination service, it is specific to asp.net mvc UI and should know a lot about it. My service mediates validation process between model and UI.
Valentin Vasiliev
Even so, you would make things a lot easier if you can get rid of the circular dependency...
Mark Seemann