Windsor style convention over configuration in StructureMap

So I was trying to get my  BDD project SpecMaker working on Mono only to find out  my usual IoC container of choice Castle Windsor does not play nice.  StructureMap I’ve heard plays nice in Mono, and I know a bunch of people that use it, so I gave it a whirl.

My original Windsor configuration looked something like this:

 var kernel = new DefaultKernel();
 kernel.Register(Component.For<IReportFactory>().ImplementedBy(factory)); //load implementation
                WithService.FirstInterface().  //regardless of naming first interface is listed as service

I changed this to the what I thought was the StructureMap equivalent:

 var container = new Container(registry =>
                registry.Scan(x =>
                    x.With<DefaultConventionScanner>(); //does NOT configure the first service interface
container.SetDefault(typeof(IReportFactory), new ConfiguredInstance(factory)); //specific implemenation

Ok so I ran my code and nearly none of my classes were registered only interfaces and classes that were in a pattern like ISpecFinder/SpecFinder.  Looking at SM’s site this is actually expected behavior, and I was not able to find anything that would work the same way as I was used to. I’m not personally a fan of naming interfaces exactly like class names, so after looking around a bit at my options with SM and a brief perusal of Windsor’s source, I used StructureMap’s extensibility to come up with the following:

class FirstInterfaceConvention : TypeRules,ITypeScanner
        public void Process(Type type, PluginGraph graph)
            if (!IsConcrete(type)) return;  //only works on concrete types
            var firstinterface = type.GetInterfaces().FirstOrDefault(); //grabs first interface
                graph.AddType(firstinterface, type); //registers type
                graph.AddType(type); //adds concrete types with no interfaces
    public class IoCConfig
        public virtual ISpecRunner InitializeRunner(Type factory)
            var container = new Container(x=> x.Scan(
            container.SetDefault(typeof(IReportFactory), new ConfiguredInstance(factory));

            return container.GetInstance<ISpecRunner>();

and perfecto!  Everything now works as it did before and I was happy that something that wasn’t supported out of the box was so very simple to add myself. Finally, SpecMaker now appears to be working in mono and is nearing a release for me which I will share shortly.

About Ryan Svihla

I consider myself a full stack polyglot, and I have been writing a lot of JS and Ruby as of late. Currently, I'm a solutions architect at DataStax
This entry was posted in Castle, Spec, SpecMaker, StructureMap. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Eyston

    Thanks, shamelessly cut/pasted.

    I had always meant to look into doing conventions, but this made it easier than procrastinating.

  • Just an FYI, you can use:
    instead of:
    container.SetDefault(typeof(IReportFactory), new ConfiguredInstance(factory));

  • Another tip for someone moving from Windsor to StructureMap: you do not need to configure concrete types.
    In your convention scanner, you can simply have:
    if(firstinterface!=null) graph.AddType(firstinterface, type);
    with no “else”.