How do you Inject a list of objects into a constructor in Castle Windsor
castle-windsor, dependency-injection, list
Solution
I've worked it out, if anyone has any feedback on whether this is a good/best solution I'd be very interested
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel, true));
container.Register(
Component.For<IImageUpdater>()
.ImplementedBy<ApplicationTileFrontImageUpdater>()
.DependsOn(Property.ForKey<ApplicationUnits>().Eq(ApplicationUnits.Metric))
.Named("ApplicationTileFrontImageUpdaterMetric")
);
container.Register(
Component.For<IImageUpdater>()
.ImplementedBy<ApplicationTileFrontImageUpdater>()
.DependsOn(Property.ForKey<ApplicationUnits>().Eq(ApplicationUnits.Imperial))
.Named("ApplicationTileFrontImageUpdaterImperial")
);
....
container.Register(
Component.For<TestImageUpdaterClass>()
.ImplementedBy<TestImageUpdaterClass>()
);
var tiuc = container.Resolve<TestImageUpdaterClass>();
Assert.AreEqual(13, tiuc.ImageUpdaters.Count);
Then for test purposes a class that consumes a list of IImageUpdaters
public class TestImageUpdaterClass
{
public IList<IImageUpdater> ImageUpdaters { get; set; }
public TestImageUpdaterClass(IList<IImageUpdater> imageUpdaters)
{
ImageUpdaters = imageUpdaters;
}
}
Problem
How do I convert this to Constructor Injection in Castle Windsor (it seems to be related to this question Windsor Castle resolving multiple dependencies with same interface but I think my example is a bit more complicated?). ``` public class ImageUpdaters : List<IImageUpdater> { public ImageUpdaters() { Add(new ApplicationTileBackImageUpdater(ApplicationUnits.Imperial)); Add(new ApplicationTileBackImageUpdater(ApplicationUnits.Metric)); Add(new ApplicationTileFrontImageUpdater(ApplicationUnits.Imperial)); Add(new ApplicationTileFrontImageUpdater(ApplicationUnits.Metric)); ... } } ``` It's not quite as simple as just passing in a list of all the implementations of IImageUpdater since most are parameterised. I have another slightly more complicated example where some objects need to share the same instance ``` public DataProcessors() { var snowReportRetriever = new CachingDataRetriever(new UriRetriever("http://..")); var notificationSender = new NotificationSender(new MessageGenerator(new SQLDataReader()), new MessageSender()); var snowDepthProcessor = new DataProcessor<SnowDepthModel>( "SnowDepthFact" , snowReportRetriever , new SnowDepthParser() , new SnowDepthModelPersistor() , new SnowDepthModelNotifier(notificationSender) , new SQLDataReader()); var runsOfTheDayProcessor = new DataProcessor<ModelList<RunsOfTheDayModel>> ( "RunsOfTheDayFact" , snowReportRetriever , new RunsOfTheDayParser() , new RunsOfTheDayModelPersistor() , new SQLDataReader()); ... ``` EDIT: I'm getting somewhere, I can register the individual ImageUpdaters and the List but the list is empty so my assertion fails? ``` container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel, true)); container.Register( Component.For<IList<IImageUpdater>>() .ImplementedBy<List<IImageUpdater>>() ); container.Register( Component.For<IImageUpdater>() .ImplementedBy<ApplicationTileFrontImageUpdater>() .DependsOn(Property.ForKey<ApplicationUnits>().Eq(ApplicationUnits.Metric)) .Named("ApplicationTileFrontImageUpdaterMetric") ); ... var imageUpdaters = container.Resolve<IList<IImageUpdater>>(); Assert.AreEqual(13,imageUpdaters.Count); ```