Neat Tricks with StructureMap

I’ve been getting a crash course in StructureMap the past 2 weeks. It’s been going pretty well especially when you consider that the author/maintainer sits next to me every day :)

We’ve been using the new 2.5-ish trunk code and there are some cool features I’d like to share with you and maybe get you pumped about the upcoming 2.5 release.

Auto-registration of obvious types

This one is particularly cool since most of the types registered in your container are ISomeService with an associated SomeService implementation.

Simply put:  If you have a class Foo that implements interface IFoo, StructureMap, if asked to do so, will auto-register Foo as the default concrete type for plugin family IFoo. No config necessary!  Phew… just saved the world some serious angle brackets tax there. Every bit counts, trust me — I came from a SpringFramework.NET background which is rich in its XML configuration.

Convention-based Discovery/Registration

When calling StructureMapConfiguration.ScanAssemblies(), you can now provide your own type registration conventions in addition to the default one. For example:

   1: StructureMapConfiguration.ScanAssemblies()
   2:     .With<DefaultConventionScanner>()
   3:     .With<YourCustomConvention>();

 

StructureMap will call a method on YourCustomConvention for each Type it finds, allowing you to do fancy things such as:

   1: if (CanBeCast(typeof (IController), type))
   2: {
   3:     string name = type.Name.Replace("Controller", "").ToLower();
   4:     registry.AddInstanceOf(typeof (IController), new ConfiguredInstance(type).WithName(name));
   5: }

This allows us, in our MVC application to register all of our controllers using their short name (i.e. LoginController -> “login”) so that they can be loaded via our custom StructureMapControllerFactory.

On-the-fly Dependency Satisfaction

This one comes in handy, but I feel a little dirty when I use it — as though I’m cheating IoC somehow. It’s cool nonetheless:

I have a service that takes the current HttpContext from ASP.NET in order to function. I then needed to pass this service into yet another service in order to construct it properly. There are a couple different ways of accomplishing this, but for this example, I’ll do it this way just to illustrate the point:

   1: ObjectFactory
   2:     .With<ISecurityContext>(new HttpSecurityContext(HttpContext.Current))
   3:     .GetInstance<AuthenticationService>();

In order to get my AuthenticationService instance, I needed an ISecurityContext — particularly the HttpSecurityContext which takes the current HttpContext.

More to Come

As I learn more I’ll post ‘em.  Also, I think Jeremy has a few more tricks up his sleeve before the release so keep an eye on his blog and the StructureMap web site for more news.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Chad Myers

Chad Myers is the Director of Development for Dovetail Software, in Austin, TX, where he leads a premiere software team building complex enterprise software products. Chad is a .NET software developer specializing in enterprise software designs and architectures. He has over 12 years of software development experience and a proven track record of Agile, test-driven project leadership using both Microsoft and open source tools. He is a community leader who speaks at the Austin .NET User's Group, the ADNUG Code Camp, and participates in various development communities and open source projects.
This entry was posted in StructureMap. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://stevenharman.net Steven Harman

    Auto-Register already exists…? Damn it!

    I actually wrote an “Auto-Wire” extension method for my current project and just checked it into CodeIncubator earlier tonight and was planning to blog about it tomorrow. Heck, maybe I’ll still blog it b/c its kinda cool.

    We’re running a version off of trunk from about 2 months ago – so maybe this feature didn’t exist then?

    btw – you can see my AutoWiring extension and tests over at http://codeincubator.com (http://code.google.com/p/codeincubator/source/browse/Tools/trunk/CodeInc.Tools/CodeInc.Commons/Extensions/StructureMap/RegistryExtensions.cs)

  • http://colinjack.blogspot.com Colin Jack

    “This one is particularly cool since most of the types registered in your container are ISomeService with an associated SomeService implementation.”

    Like the auto-registration idea but I do think if I were continually putting in ISomeService style interfaces then I’d want to be thinking about whether I was making the right choices. I’m not convinced that ISomeService style interfaces are that great because they are not useful abstractions, they don’t simplify the system and they usually don’t decouple in ways that I find useful. Depends on how you use them I guess, and for things like controllers I can definitely see it being a good idea.

    Of course if I am using those sorts of interfaces then auto-registration would be useful, just as the auto-mocking container is for this sort of thing.

  • http://chadmyers.lostechies.com Chad Myers

    @Colin:

    With a few exceptions, our service interfaces help facilitate testing and we usually have a stub variant of them so we can do integration and manual testing without actually going out and doing something (hitting the DB, calling a web service, writing a file, etc).

    As I understand it, interface abstraction allows for wildly differing implementation bound to a specific contract of interaction. With that goal, our services work very well.

    Auto registration is useful when running normal/real so that you don’t need extra configuration for the 99% case (we only require extra config in the 1% case).

  • http://colinjack.blogspot.com Colin Jack

    @Chad
    I know I’m like a broken record on this but it does interest me :)

    I get the testing argument but normally along with it goes along arguments about improving the design and dependency inversion and all the good stuff. However I just don’t think that the interface/implementation style of interface helps much and then they become a pain so we engineer around them (auto-mock or auto-register). Maybe its a pain thats worth putting up with though…

    I usually find that when I want radicly different implementations I’ll design interfaces to be small and ISP compliant, designed for the clients and adding something on top of what the rest of the design gives me. However if all I’m doing is creating IFooService for my FooService then I’m not sure what I get. In particular when its for something like a repository/service, I’m really very rarely going to have multiple repositories for an aggregate or multiple different services sharing exactly the same interface (they may share parts of their interfaces though…).

    Thats my thoughts anyway.

  • http://colinjack.blogspot.com Colin Jack

    > ObjectFactory.With(new
    > HttpSecurityContext(HttpContext.Current))

    Just wondered what the other options for this sort of situtation are, where the dependency being injected has its own dependency on something scabby like HTTP context or session.

  • SimonB

    Hmm – I’m not so sure about the auto registration. I use IoC for many reasons. Testing isolation, and decoupling of the system. But I do want to make sure what gets return is what I want it to be. A few extra lines to add a entry – especially if done in initialising a registry – is not much. And I explicitly and declaratively know what I’m getting.

  • http://chadmyers.lostechies.com Chad Myers

    @SimonB: What do you gain by being explicit? Does it help the system, or it is only because it makes you feel more comfortable using IoC?

    I ask this, because I had this same opinion, and the more I used IoC and grew to trust the containers, I found that the extra explicitness was a form of coupling and caused more friction and didn’t really provide any benefit.

  • SimonB

    I suppose I get the confidence that if I don’t specify what the concrete class will be, the system will return an error. That way I don’t accidently get back the wrong class. In the past I have subtle bugs, especially in large systems, default behaiour was misunderstood. It took a long time to resolve.

  • http://chadmyers.lostechies.com Chad Myers

    @Simon: You should have tests around your container configuration to ensure that mistakes/surprises don’t happen. Please consider this whether you’re doing auto-reg or not. It helps!

  • SimonB

    Chad: Please confirm as I might be reading this wrong (I’m from Australia and it’s winter here;) but are you saying that you should have Integration tests (unit tests don’t include the IoC framework) to pickup that the IoC framework is working correctly. As by adding a class I get can different behaviour?

    This seems a little, err, … strange. Should I have to validate that someone hasn’t added a class that I don’t know about that is now being returned instead if the one I expected?

  • http://chadmyers.lostechies.com Chad Myers

    @SimonB

    It’s more of a smoke test. We test that at least one of the auto-registered types is actually register (in case a developer comes along later and turns off auto-registration). We also validate that a few of the critical services that might not have been auto-registered are, in fact, registered.

    These are more canaries in the mine shaft to let a would-be future maintenance programmer know that there are strong expectations about what’s expected to be in the container.