Sep 15
Injecting all instances of a given type
icon1 Darrell Mozingo | icon2 Misc. | icon4 September 15th, 2009| icon35 Comments »

I’m sure I’m a little late to the game here, but I recently stumbled across how to do collection injection with Structure Map. I’ve known it was possible, and have seen it hinted at in other blogs posts for a while, but I just didn’t know how exactly it was done.

Why would you want to do this? Lets take an actual situation from our system. We rolled a small scheduled task framework (sorry Quartz.NET and Topshelf, you just didn’t fit the bill for our needs). I wanted us to just drop a POCO object in the project and implement an ITask interface, which had exactly one method: Run(). I also wanted these objects to be pulled from the container so they could have services/repositories injected in as needed.

To make it easy for our network admins to schedule these tasks, I wrote the application to take a single /run <taskName> parameter. So if you wanted to run the EmailUsersTask, you’d simply run the app with /run EmailUsers. I also added a TaskDescription attribute so task authors could add a single sentence letting everyone know what it did, which would be displayed when the user ran the app with no parameters in a list with all the available tasks and a description of each.

Simple enough, right?

My first stab at it, and it actually ran for a while like this, took in Structure Map’s IContainer to retrieve the task with all its dependencies satisfied, and to display all the available tasks it would just loop through all types in the assembly (filtered for only those implementing ITask), and get the needed display information.

Worked fine and dandy, but testing it was slow. I had to scan all the types in the assembly, even if I knew I was looking for a single test dummy class. I didn’t like it, so I began tinkering with Structure Map. I wanted the fully initialized objects (from the container) injected in as an IEnumerable<ITask>, so I could just pluck the needed one to run, and loop through that list to build up the small display when needed. It would be easier to read and also make testing quicker and simpler. Here’s what I ended up with:

public static void BootstrapStructureMap()
{
	ObjectFactory.Initialize(y =>
	                         {
	                         	y.Scan(x =>
	                         	       {
	                         	       	x.TheCallingAssembly();
						x.WithDefaultConventions();
						x.AddAllTypesOf<ITask>();
	                         	       });
 
					y.ForRequestedType<IEnumerable<ITask>>()
	                         		.TheDefault.Is.ConstructedBy(x => ObjectFactory.GetAllInstances<ITask>());
	                         });
}

This is called while our app is boot strapping (though we use separate Registries for each area of the app, I just simplified it for posting). Pretty self explanatory – the AddAllTypesOf tells Structure Map to gather up all implementors of ITask in the assembly, and we then tell Structure Map to get all instances of that interface to pass it in whenever IEnumerable<ITask> is requested. Without that, you’d have to take in an array of ITask's. Same difference, I just prefer enumerables.

So there you go – get a collection of fully constructed types injected into your objects. We did this assembly type looping in one or two other system startup areas of the app, and I was able to kill them all off with this technique while shaving a good 4 seconds off our unit test suite. Pretty neato.

As a moral, of sorts, for this story, I also learned after doing all this to always RTFM when you have a question. It’ll save you a lot of time tinkering on your own 🙂

Sep 1
2009 Goals – September Update
icon1 Darrell Mozingo | icon2 Goals | icon4 September 1st, 2009| icon31 Comment »

Three quarters of the way through 2009. How am I doing on my goals for the year? Let’s see (comments in italics after each goal):

Books

  1. Code Complete – Steve McConnell (yep, I’ve never actually read it)    No progress.
  2. Patterns of Enterprise Application Architecture – Martin Fowler    Ready to start here soon.
  3. Domain Driven Design – Erick Evans    Done.
  4. Working Effectively With Legacy Code – Robert Martin    I think we’re getting close to needing a messaging framework, but I’m not quite ready to introduce the knowledge overhead for the team yet.

Tools/Techniques/Processes @ Work

  • NHibernate and all its trimmings (FluentNHibernate, LINQ to NHibernate, etc), which I’ll need on a project here real soon.  Done, but still picking up stuff.
  • Actually move from CC.NET to Team City (last attempt didn’t go so well).  No progress.
  • Build a more robust build script and management process – including production deployment scenarios.   No progress.
  • Messaging framework, either MassTransit, NServiceBus, or Ayende’s new Rhino Service Bus if he’s able to release it in time for our current project.  No progress as we haven’t needed any yet.

Involvement

  • We have weekly meetings to catch everyone up on what we’re doing, but I want to present on an actual topic during at least 2 of these – and present in a way where the other development teams will see the use in picking up the presented tool/technique.    Our meetings are still halted, but I’m hoping to do an intro IoC/DI presentation if they ever start again.
  • Have at least one meeting of the CantonALT.NET group and see if it can ever get up on its feet.   No progress, but we’ve had quite a few more Code & Coffee get togethers, and we’re talking about getting a meeting together that’s not quite as tied to ALT.NET (some of the guys used to run them back in the early oughts).
  • The two blog posts per month target John put out there seems doable, so I’ll borrow it 🙂    Still on target, thought I’m starting to run out of post ideas. Might need to think up another series on something.
  • At least 3 feature/patch submissions to open source projects.  No further progress past the last update.

Productivity

  • Trim RSS feed size by 1/3 (presently at 127, so trim it to at least 85) and cut time viewing it by half. I’ve gotten much better this past year at cutting through the useless stuff, but there’s still a lot there and it sucks up too much of my time.  Down to 89. Went on a feed cutting spree a few weeks back, mostly dead ones and others that have wondered into other topics that don’t interest me as much.

I’ll just point to the reading again. No more excuses – I just can’t read technical books for long periods of time, especially dense ones, which are oddly the ones I want to read.

I’ll update again in the beginning of November.