Reputation: 4571
Using Castle Windsor, I want to get the collection of all factories that implement a particular interface.
Say you have the following type hierarchy:
public interface IAnimal { }
public class Cat : IAnimal { }
public class Dog : IAnimal { }
using TypedFactoryFacility
I am able to inject a Func<IAnimal>
that acts as a factory to create animal instances (with transient life cycle). I can also use CollectionResolver
to resolve a collection of animals with singleton life cycles. But in the following example, it seems that you cannot combine the effects of TypedFactoryFacility
and CollectionResolver
to resolve a collection of factories.
public class Zoo
{
public Zoo(IEnumerable<Func<IAnimal>> animalFactories)
{
foreach (Func<IAnimal> factory in animalFactories)
{
IAnimal animal = factory();
Console.WriteLine(animal.GetType());
}
}
}
class Test
{
static void Main(string[] args)
{
IWindsorContainer container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));
container.Register(Component.For<IAnimal>().ImplementedBy<Cat>().LifestyleTransient());
container.Register(Component.For<IAnimal>().ImplementedBy<Dog>().LifestyleTransient());
container.Register(Component.For<Zoo>());
container.ResolveAll<IAnimal>();
container.Resolve<Zoo>();
}
}
This results in the following error:
Component Zoo has a dependency on System.Collections.Generic.IEnumerable`1[System.Func`1[IAnimal]], which could not be resolved.
Upvotes: 1
Views: 1316
Reputation: 6251
You have to do these steps :
Register an interface as factory with the lifetime that suits your needs. The interface has no impleentation because it is castle typed factory facility. I register such providers as singletons :
Component.For().AsFactory()
I intentionally name it provider because it does not create new intances by some logic but provides you the already registered instances.
The interface must look like this :
public interface IAnimalFactoryProvider { IEnumerable<IAnimalFactory> GetAllAnimalFactories(); void Release(IAnimalFactory animalFactory); }
Then you put IModuleModelInitializerProvider in a ctor that you want it injected and then get all hte instances through the method GetAllAnimalFactories().
Then depending on your IAnimal factories you may release them after use or if they are singletons too you can just leave them and Castle will dispose them when your application quits.
Another approach - typed factory as delegate is described here, here, here, here and here
Upvotes: 2