How to properly decouple Structure Map dependency resolver from ASP.NET MVC web project?

1.3k views Asked by At

While developing web project using ASP.NET MVC, I came up against a coupling problem. When I build custom controller factory (or dependency resolver if using MVC 3), I need this factory to know somehow where to get dependencies from. Here's my code:

//from Global.asax.cs

DependencyResolver.SetResolver(new StructureMapControllerFactory());
class StructureMapControllerFactory: IDependencyResolver {
    Container repositories;

    public StructureMapControllerFactory()
    {
        repositories = new RepositoriesContainer();
    }
    //... rest of the implementation
}
class RepositoriesContainer: Container
{
   public RepositoriesContainer()
   {
      For<IAccountRepository>().Use<SqlAccountRepository>();
      //...
   }
}

StructureMapControllerFactory class is responsible for injecting dependencies into a controller. As I said, it needs to know where to find these dependencies (I mean concrete classes, like services and repositories implementations).

I have a separate class library called MySite.Data, where all the implementation details live. Contracts, like IAccountRepository, live in library MySite.Contracts. Now, if I reference this MySite.Data library directly from MVC project, there will be a dependency between my site and implementation of its data retrieval. The question is how can I remove it? What are best practices in this situation?

I'm sure it does have a bunch of workarounds, just I haven't found any yet.

1

There are 1 answers

0
Vasiliy R On BEST ANSWER

Well, as I see it, you can't do exactly that. Your MVC project really really needs to know about concrete classes it is going to use.

You will anyway have to provide those container registrations somewhere and you'll get the dependency on the project/assembly where that type is defined. Shortly, you have to reference MySite.Data from MVC project. Like that:

  • MySite.Data knows nothing about MVC project
  • MVC project knows the concrete repositories types to provide correct container registrations.

You can make life simpler with StructureMap Registry objects but you need to include those Registries somewhere as well. Typically those are in the main project or some "StructureMap-adapter" project but you'd need to make reference anyway.

I'd advise that you:

  • Use MVC3 and drop your custom IControllerFactory if you only use it for DI into your Controllers.
  • Use StructureMap Registry objects to provide each and every IoC registration ever needed.
  • Use StructureMap Assembly scanning capabilities to provide components discovery.
  • Use something much more common as a DependencyResolver, i.e. not a StructureMapControllerFactory but a CommonServiceLocator with StructureMap adapter instead.
  • Try to abstract from StructureMap itself inside your main app.

And, of course, don't be afraid of making references inside the main project - they have nothing about coupling. It doesn't decrease maintainability. But the wrong architecture does, so be worried about that, not simple reference.