0
votes

I have a class that has several dependencies:

public class ThirdPartyDataSearchCoordinator<TItem, TSearchCriteria, TResult> : IThirdPartyDataSearchCoordinator where TItem : class, IThirdPartyItem
    {
        public ThirdPartyDataSearchCoordinator(IDataMiner<TSearchCriteria, TResult>[] miners, IThirdPartyItemRepository<TItem> repository, IMappingEngine mapper, IUpdater<TItem, TResult> updater)
        {
            this.miners = miners;
            this.repository = repository;
            this.mapper = mapper;
            this.updater = updater;
        }
}

And the relevant Castle registrations look like this:

container.Kernel.Resolver.AddSubResolver(new ArrayResolver(container.Kernel));
container.Register(Component.For<IMappingEngine>().Instance(Mapper.Engine));
container.AddComponent<IThirdPartyItemRepository<ThirdPartyPackage>, ThirdPartyPackageRepository>(typeof(IThirdPartyItemRepository<ThirdPartyPackage>).FullName);
container.Register(AllTypes.Pick()
                    .FromAssemblyNamed(Assembly.GetAssembly(typeof(TestDataMiner)).GetName().Name)
                    .WithService.FirstInterface());
container.AddComponent<IThirdPartyDataSearchCoordinator, ThirdPartyDataSearchCoordinator<ThirdPartyPackage,ThirdPartyPackageSearchCriteriaDto,ThirdPartyFlightSearchResultDto>>();

However, I'm having real trouble resolving an instance of IThirdPartyDataSearchCoordinator.

All these are successful:

ServiceLocator.Current.GetInstance<IThirdPartyItemRepository<ThirdPartyPackage>>()
ServiceLocator.Current.GetInstance<IUpdater<ThirdPartyPackage, ThirdPartyPackageSearchResultDto>>()
ServiceLocator.Current.GetInstance<IMappingEngine>()
ServiceLocator.Current.GetInstance<IDataMiner<ThirdPartyPackageSearchCriteriaDto, ThirdPartyPackageSearchResultDto>>()

However when I try:

ServiceLocator.Current.GetInstance<IThirdPartyDataSearchCoordinator>()

Castle complains:

Castle.MicroKernel.Handlers.HandlerException: Can't create component 'ApplicationServices.ThirdPartyData.ThirdPartyDataSearchCoordinator3' as it has dependencies to be satisfied. ApplicationServices.ThirdPartyData.ThirdPartyDataSearchCoordinator3 is waiting for the following dependencies:

Services: - IThirdPartyItemRepository1 which was not registered. - IUpdater2 which was not registered.

Keys (components with specific keys) - miners which was not registered.

Am I missing something - or am I expecting too much of Castle to resolve generic dependencies that way?

Edit What I would like to do is explicitly register each concrete ThirdPartyDataSearchCoordinator<TItem, TSearchCriteria, TResult> that I intend to use against the IThirdPartyDataSearchCoordinator interface in the application.

I don't want to make the interface generic, as then I wouldn't be able to hold a collection of different IThirdPartyDataSearchCoordinator.

How can I tell castle to explicitly initialise, for example, a ThirdPartyDataSearchCoordinator<ThirdPartyPackage, ThirdPartyPackageSearchCriteriaDto, ThirdPartyPackageSearchResultDto>, without having to feed in all the dependencies manually to the constructor?

2

2 Answers

1
votes

Not 100% sure, but I think you need to register the open generic interfaces first. Then you can override a specific implementation.

See Castle Windsor resolving and generics

1
votes

Okay I played around for quite a bit and worked a solution. I changed my "AllTypes" registration to only register non-generic types.

container.Register(AllTypes.Pick()
.FromAssemblyNamed(Assembly.GetAssembly(typeof(IUpdater<,>)).GetName().Name)
.If(p => !p.ContainsGenericParameters)
.WithService.FirstInterface());

Now it all works nicely. I think there's some problem with AllTypes and generic class registrations.

Update Simply placing my generic class registrations before the AllTypes did the trick too.