简体   繁体   中英

Castle Windsor: How to inject the collection of all factories?

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.

You have to do these steps :

  1. 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.

  1. The interface must look like this :

    public interface IAnimalFactoryProvider { IEnumerable<IAnimalFactory> GetAllAnimalFactories(); void Release(IAnimalFactory animalFactory); }

  2. Then you put IModuleModelInitializerProvider in a ctor that you want it injected and then get all hte instances through the method GetAllAnimalFactories().

  3. 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM