Factory constructor injection with Castle Windsor

787 views
Skip to first unread message

Vel Elous

unread,
Dec 6, 2013, 3:41:59 AM12/6/13
to castle-pro...@googlegroups.com

I am experimenting with the Castle Windsor IoC container, in particular looking for the "correct" method on how to inject a factory in to a constructor.

I have been reading up on the Typed Factory Facility, however, it appears that the AsFactory()method automatically generates a factory behind the scenes. I would like to make use of my ownfactory implementation. Any class which consumes the factory will provide the Create method with some arguments which will subsequently be used by the factory to determine which objectto return. Below is a contrived example of what I have:

namespace TypedFactory
{
    using System;
    using Castle.MicroKernel.Registration;
    using Castle.Windsor;

    class Program
    {
        static IWindsorContainer container;

        static void Main(string[] args)
        {
            container = new WindsorContainer();
            container.Register(
                Component.For<IMyObjectFactory>().ImplementedBy<MyObjectFactory>().LifeStyle.Singleton,
                Component.For<FactoryConsumer>()
                );

            var factoryConsumer = container.Resolve<FactoryConsumer>();
            // The following Console.WriteLine(...)
            // Prints "ToString() called from MyObjectA" to the console, so seems to work
            Console.WriteLine(factoryConsumer.Create("MyObjectA", "Some value to go to constructor"));
            Console.ReadKey();
        }
    }

    #region [ MyObject ]

    public interface IMyObject
    {
    }

    public class MyObjectA : IMyObject
    {
        private readonly string output;

        public MyObjectA(string output)
        {
            this.output = output;
        }

        public override string ToString()
        {
            return "ToString() called from " + this.GetType().Name;
        }
    }

    public class MyObjectB : IMyObject
    {
        private readonly string output;

        public MyObjectB(string output)
        {
            this.output = output;
        }

        public override string ToString()
        {
            return "ToString() called from " + this.GetType().Name;
        }
    }

    #endregion

    #region [ MyObject Factory ]

    public interface IMyObjectFactory
    {
        IMyObject Create(string make, string output);
    }

    public class MyObjectFactory : IMyObjectFactory
    {
        public IMyObject Create(string make, string output)
        {
            IMyObject myObject = null;
            switch (make)
            {
                case "MyObjectA":
                    myObject = new MyObjectA(output);
                    break;
                case "MyObjectB":
                    myObject = new MyObjectB(output);
                    ;break;
            }

            return myObject;
        }
    }

    #endregion

    public class FactoryConsumer
    {
        private readonly IMyObjectFactory objectFactory;

        public FactoryConsumer(IMyObjectFactory objectFactory)
        {
            this.objectFactory = objectFactory;
        }

        public IMyObject Create(string make, string output)
        {
            return this.objectFactory.Create(make, output);
        }
    }
}

Is the above acceptable, or is there something else I should be doing?

Anthony Abate

unread,
Dec 7, 2013, 11:01:58 AM12/7/13
to castle-pro...@googlegroups.com
Looks ok since you made the factory an interface, but here's a caveat:  

I am assuming you are using that type based switch statement because you don't know the type at compile?

If you did know the type, you could use generics and the typed factory like the following:

public interface IFactory : IDisposable
{
   TObject Create<TObject>(string ctorParam1) where TObject : IDisposable
}

I still prefer the typed factory as there is no implementation code to deal with. Since you have an interface, you could swap out your concrete factory out for the typed factory in the future just by tuning the container registration.

if am trying to do some fancy stuff with the typed factory by controlling the mechanics of object resolution using custom resolvers / subsystems... 

in mycase I have many different objects that satisfy the same type and that are registered in the container (ie plugins).  I want to create specific sets based on meta data as follows:

public interface IFactory : IDisposable
{
   List<TObject> Create<TObject>(string ctorParam1, string metaData) where TObject IDisposable
}

You may be trying to tackle the same problem I have... where you have many objects of the same type and you need to resolve a specific one based on meta data.

Vel Elous

unread,
Dec 8, 2013, 1:12:15 PM12/8/13
to castle-pro...@googlegroups.com
It does appear that we are working on a similar scenario.

Anthony Abate

unread,
Dec 9, 2013, 8:15:09 AM12/9/13
to castle-pro...@googlegroups.com

I came across something called the NamingPartsSubsystem (see my post a few days ago with the same name)    

I could have made it work with that, but it appears to be removed / broken in castle 3.x

--
You received this message because you are subscribed to a topic in the Google Groups "Castle Project Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/castle-project-users/TiW2LBsxB74/unsubscribe.
To unsubscribe from this group and all its topics, send an email to castle-project-u...@googlegroups.com.
To post to this group, send email to castle-pro...@googlegroups.com.
Visit this group at http://groups.google.com/group/castle-project-users.
For more options, visit https://groups.google.com/groups/opt_out.
Reply all
Reply to author
Forward
0 new messages