New StructureMap on the horizon

Since a week or so, I’m using the latest StructureMap SVN snapshot in one of my projects. I’m a big fan of StructureMap and prefer it over Windsor, because most of my use cases don’t require very complex DI stuff. Most of the time I’m injecting IView’s or IService’s into Controller’s and StructureMap makes this as easy as:

[PluginFamily("View")]
public interface IView
{
}

[Pluggable("View")]
public class View: IView
{
}

public class Controller
{
    public Controller(IView view)
    {
    }
}

But back to the new StructureMap features. In the last version it was necessary to configure the Controller class from the above example as well, to be able to instantiate it from the StructureMap DI container:

[PluginFamily("Controller"), Pluggable("Controller") ]
public class Controller
{
 ....

In the upcoming StructureMap release every concrete class can be configured without explicitly configuring it (provided that all constructor dependencies can be resolved). This wasn’t too hard to do in the previous release with ObjectFactory.FillDependencies<ConcreteClass>(), but to be honest, I never thought of using this and am happy, that I can now get rid off some of the “attribute noise”.

Much more interesting is the new ability to pass parameters to the constructor, when instantiating a class through the DI container:

public class Controller
{
    public Controller (IService service, Parameter parameter)
    {
    }
}
...
ObjectFactory.With<Parameter>(parameter).GetInstance<Controller>()

This will automatically pass the provided parameter to the constructor, which is very nice for passing around state / model objects. This gives some really nice possibilities in the infrastructure layer, where instances are requested from the DI container. In my ApplicationShell class I can now have something like this:

public void GoTo<TController, TParameter>(TParameter Parameter) where TController: IController
{
    TController controller = ObjectFactory.With(Parameter).GetInstance<TController>();
    SwitchToView(controller.View);
    controller.Initialize();
 }

So in order to e.g. pass a Sale object from a SaleController to PaymentController it’s simply:

public class SaleController
{
    private Sale _currentSale;

    public void RequestPayment()
    {
        _applicationShell.GoTo<PaymentController, Sale>(_currentSale);
    }
}

Last but not least, StructureMap now also supports AutoMocking. It’s still a little bit rough around the edges, but with some very small modifications (basically to use DynamicMocks by default), I could make it usable for me.

[TestFixture]
public class A_ReportSelectionController_with_some_reports :
  AutoMockingTestFixture<ReportSelectionController>
{
    private ReportSelectionController _controller;
    private List<ReportDefinition> _listOfReports;

    [SetUp]
    public override void SetUp()
    {
        base.SetUp();
        _controller = AutoMocker.CreatePartialMocked();
        AutoMocker.BackToRecordAll();
        _listOfReports = SetUpSampleReports();
        SetupResult.For(Service<IReportsConfiguration>()
         .GetReportDefinitions()).Return(_listOfReports);
    }

    [Test]
    public void Should_run_the_selected_report()
    {
        using (AutoMocker.Record())
        {
            Service<IApplicationShell>().GoTo<ReportController>(_listOfReports[1]);
        }

        using (AutoMocker.Playback())
        {
            _controller.Initialize();
            _controller.SelectReport(1);
            _controller.RunSelectedReport();
        }
    }
}

public class AutoMockingTestFixture<T> where T: class
{
    private RhinoAutoMocker<T> _autoMocker;

    [SetUp]
    public virtual void SetUp()
    {
        _autoMocker = new RhinoAutoMocker<T>();
    }

    protected RhinoAutoMocker<T> AutoMocker
    {
        get { return _autoMocker; }
    }

    protected TService Service<TService>()
    {
        return _autoMocker.Service<TService>();
    }
}

All in all: StructureMap’s new features make it a really nice product coming with less DLL’s than a full blown Castle Windsor DI ;-) Thanks Jeremy!

UPDATE: Jeremy just changed the AutoMocker to use DynamicMock by default

Tags , , ,

Posted in | Posted on 12 Feb 2008 16:33by Tobi | no comments

Comments

Leave a comment