Originally, I was using an overload of UnityContainer.RegisterType that took generic type parameters. This is well-and-good, but because generic type parameters are really only helpful at compile-time, this approach would have required each new implementation to add an individual line of additional code to call RegisterType.
container.RegisterType<ICameraDataService, SeattleCameraDataService>( typeof(SeattleCameraDataService).Name, new ContainerControlledLifetimeManager()); container.RegisterType<ICameraDataService, BayAreaCameraDataService>( typeof(BayAreaCameraDataService).Name, new ContainerControlledLifetimeManager()); // etc.
Ideally, this would not be necessary, as it is an additional step for the camera data contributor and is prone to error. Fortunately, we can reflect over all of the types in the assembly looking for appropriate implementations and use a non-generic RegisterType overload as follows:
var cameraDataServiceTypes = from t in Assembly.GetExecutingAssembly().GetTypes() where t.IsClass && !t.IsAbstract && t.GetInterface(typeof(ICameraDataService).Name) != null select t; foreach (var cameraDataServiceType in cameraDataServiceTypes) { container.RegisterType(typeof(ICameraDataService), cameraDataServiceType, cameraDataServiceType.Name, new ContainerControlledLifetimeManager(), new InjectionMember[] { }); }
Later, since Unity is happy with multiple registered implementations per interface, these can be snarfed out of the container using UnityContainer.ResolveAll:
var managers = UnityConfig.GetConfiguredContainer().ResolveAll(typeof(ICameraDataService)); foreach (ICameraDataService manager in managers) { var service = manager as ICameraDataService; services[service.Name] = service; }