views:

143

answers:

3

I'm going to use structuremap for a project I'm working on. The basic gist is that I have a repository pattern with an NHibernate implementation, but I want to use StructureMap to load the repositories in case I ever decide to switch to a Linq2Sql or other type of implementation. I know how to initialize structuremap, but my question is where? Should the web application that uses my library be responsible for configuring the registry? Should I have a default implementation in my library? Where would it fit best?

My library structure at the moment looks like:

  • Library.Data
  • Library.Data.NHibernate
  • Library.Domain

The .Domain namespace contains the actual entities, while the .Data namespace contains the interfaces for the repository. The .Data.NHibernate namespace contains the NHibernate implementation of those interfaces.

+2  A: 

When using IoC containers, the calling application should ideally be responsible for configuring all dependencies.

A well-structured system will demand dependent objects as constructor parameters. How you invoke those constructors is independent of StructureMap or any other technique, but can only be specified at the point at which the "top most" object is used. Separation in this way will allow applications to inject dependencies in whichever way they desire and gives you that warm fuzzy feeling you can only get from having great separation of concerns.

I'm not entirely sure what you mean by a "default" implementation in the context of your library. Your "default" implementation (configured by your StructureMap registry) will be the instance you get back when you ask StructureMap for an implementation of a given interface (presumably some kind of IRepository in your case), without specifying any other criteria.

For you, you will want this instance to be configured as your NHibernate implementation. Presumably this implementation already lives in the Library.Data.NHibernate namespace as your "NHibernate Repository". You shouldn't need to create any other implementation unless you want to change your IRepository implementation to something else.

Programming Hero
In my case, the application is fairly simple, so the web application will be using the repositories directly. My only wish is to do so in a way that allows me to switch out the repositories with a single configuration change. Sounds like I should probably put this in the application_start event of my ASP.NET site. I just wasn't sure if it was typical to require the client application to handle so much configuration up front. I like the configuration over convention mentality myself.
Chris
Er, that should be convention over configuration mentality.
Chris
Application_Start is an ideal place to build your Registry. Configuring all your dependencies there is the best way to go for keeping it all in one place.
Programming Hero
> When using IoC containers, the calling application should ideally be responsible for configuring all dependenciesThat's not really inversion of control, is it?
Matt Hinze
That's precisely inversion of control. Normally the object controls its own dependencies and the application controls just the object. With IoC, the application controls the dependencies as well as the object. So, for example, rather than a component creating an object for logging, your application is responsible for passing it a logging object. Inversion of Control.
Programming Hero
A: 

I had the same question some time ago and finally i ended creating a registry class on each project and calling them in cascade.

I'll update with some code when i get home.

Update

I had 3 projects (Web, Services and Data) but i did not want to add a reference to Data in my Web project for example, so what i did is that every project is responsible of registering it's own Interfaces.

For example, In my Web project i created the class WebRegistry that not only register its own types but also calls the ServicesRegistry class in my Services project and so on.

WebRegistry:

public class WebRegistry : Registry
{
    public WebRegistry()
        {
            ObjectFactory.Configure(x =>
            {
                //call to ServicesRegistry in my services project
                x.AddRegistry(new ServicesRegistry());

                //Register your web classes here
                ForRequestedType... blablablabla

            });

        }
}

ServicesRegistry:

public class ServicesRegistry : Registry
{
    public ServicesRegistry()
    {
        ObjectFactory.Configure(x =>
        {
            x.AddRegistry(new DataRegistry());

            //Register your services classes here
            ForRequestedType... blablablabla
        });

    }
}

And finally the DataRegistry:

public class DataRegistry : Registry
{
    public DataRegistry()
    {
        ObjectFactory.Configure(x =>
        {
            ForRequestedType blablbabla....

        });
    }
}

I think this way everything is completely idependant and you only need one call to the webregistry in your global.asax to configure the entire application:

/// <summary>
/// 
/// </summary>
public class Bootstrapper
{

    /// <summary>
    /// 
    /// </summary>
    public static void ConfigureStructureMap()
    {
        ObjectFactory.Initialize(x =>
        {
            x.AddRegistry(new WebRegistry());
        });
    }


}

Global.asax:

    protected void Application_Start()
    {

        Bootstrapper.ConfigureStructureMap();


    }
Drevak
A: 

Inversion of control configuration can be done in one of two places: in the calling assembly or in another assembly.

If you want to do it in the calling assembly (which couples it to the IOC tool), just do it in Global.asax.cs or in a class called there.

If you want to do it in another assembly, use an HTTP Module, like this: http://codecampserver.googlecode.com/svn/trunk/src/DependencyResolution/DependencyRegistrarModule.cs

Matt Hinze