views:

146

answers:

1

I am fairly new to StructureMap, but my understanding is that there are two ways of getting an instance from the ObjectFactory:

  1. By type (i.e. ObjectFactory.GetInstance<IFoo>())
  2. By type and name (i.e. ObjectFactory.GetNamedInstance<IFoo>("foo.bar"))

I have seen a multitude of examples out there demonstrating how to create an MVC Controller Factory that will provide controller instances using StructureMap, and in most cases I have seen, they are using the method from option #1 above.

Let's say we have some controller that accepts a repository/DAO interface as a constructor arg...

public class FooController : Controller
{
  public FooController (IFooRepository fooRepository)
  {
     // constructor code goes here
  }
}

Using the interface class gives me the ability to "inject" any implementation of that interface in to my controller. What if for two different actions, I want to inject different implementations? Perhaps in one case, I need an implementation of my repository that will query a SQL Server database, and in another case, I need an implementation that will get data from an XML file or through a Web Service call.

It seems that if you use the ObjectFactory.GetInstance() method, you would be restricted to only providing your controller with a single implementation of your repository interface.

However, if you go with named instances, then you will end up having to create the instances based on the name of the controller that the MVC framework provides. In most cases, this will typically be the controller name coming from the URL, but it's really up to the route configuration. This seems like it could be very confusing, and would only get more confusing as the number of routes increased.

Is there any alternative method that would allow for different controller instantiation strategies without using named instances? Would it be a better idea to just create separate controllers, and make sure that all the actions in any given controller will be valid for the same concrete instance of a repository/DAO class?

A: 

For what it's worth, I ended up going with named instances, where the names of each instance are based on the name of the controller that the MVC framework pulls from the URL.

For instance, the URL /foo/DoSomething might get an IController instance from the ObjectFactory that is instantiated with a Repository object that uses the SqlClient API for data access. A URL such as /foo.webservice/DoSomething would then create an instance of the same concrete controller class, but pass that instance's constructor a repository object that uses a web service for data access.

There are several ways to override StructureMap's default auto-wiring behavior for constructor arguments. In my case, I used the CtorDependency and Is methods, and had mappings that looked something like this...

// create a named instance for the "foo" controller that uses the SqlClient based repository
InstanceOf<IController>()
    .Is.OfConcreteType<FooController>()
    .CtorDependency<IFooRepository>()
    .Is(new FooRepositorySql(Constants.FooConnectionString))
    .WithName("foo");

// create a named instance for the "foo.webservice" controller that uses the Web Service based repository
InstanceOf<IController>()
    .Is.OfConcreteType<FooController>()
    .CtorDependency<IFooRepository>()
    .Is(new FooRepositoryWs(Constants.FooServiceUrl))
    .WithName("foo.webservice");
Justin Holzer