One of the nice things about finally finishing a major project is that you get to do some work on side projects you find entertaining. So, today, I finally finished a rather ugly merge and got a new version of AutoGen for Castle out. Obviously, it isn’t hard to implement the Common Service Locator in Windsor. However, since the idea of AutoGen was to allow you to use your own abstraction for DI, and so implementing Microsoft’s seemed like a good stress test. I’ll take a crack at NServiceBus next… 🙂
I shamelessly ripped off Ayende’s tests for the CSL and ran them against an AutoGen version of the implementation. I identified a number of issues:
- You couldn’t specify a service type. This isn’t important if you’re building an application, because you’d just specify a return type and AutoGen would handle it. However, a framework doesn’t necessarily know the service type in advance, so framework interfaces need that feature.
- You couldn’t perform a ResolveAll. Now, if you return IEnumerable<T>, it automatically performs a resolve all. This would interfere with anyone who registered an IEnumerable<T> service type, but frankly, Castle’s dependency injection pretty much fails when you do that anyway.
- The Common Service Locator standard specifies the exception that needs to be thrown.
Anyway, the good news is that it this now works:
container.Register( Component .For<IServiceLocator>() .AutoGen() .WithWrappedException<ActivationException>() );
I also took the opportunity to allow you to override the names of the key and serviceType parameters, both in configuration and using the fluent API, since it seemed likely this would come up when implementing third party interfaces. I’m not massively happy with the wrapped exception qualifier, it feels a bit too special case (time will tell, it may prove useful in a number of circumstances). It’s implemented as a separate interceptor. I’d have liked to have properly separated the concerns of resolution and disposal proxying, but it turns out that this is nigh-on impossible. Basically, since proxying of concrete classes is fraught with difficulty, to say the least, you need to know what the original service type was in order to create a valid proxy. It automatically adds in proxy interfaces for anything else the implementation exposes, which means that forwarding now works transparently.