David Hayes
David Hayes

Reputation: 7522

How do you Inject a list of objects into a constructor in Castle Windsor

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);

Upvotes: 3

Views: 1655

Answers (1)

David Hayes
David Hayes

Reputation: 7522

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;
        }
    }

Upvotes: 4

Related Questions