A Generic Factory in C#

There is this really popular OOP design pattern that we at Tranxition, and other developers elsewhere, use frequently.  Years ago, after reading about the factory pattern in the GOF book I immediately thought of some possible uses for it in my work.  I was really excited to code it up… the first time.  After having writing the code for one factory though, it was clear to me it should just be a library and there were some things overlooked by most example implementations.

Here’s a classic example from a simple drawing program:

public class ShapeFactory

{

    public Shape CreateObject(ShapeName shapeName)

    {

        switch (shapeName)

        {

            case ShapeName.Circle:

                return new Circle();

            case ShapeName.Square:

                return new Square();

            default:

                throw new Exception(“unknown shape type”);

        }

    }

}

The solution this ShapeFactory provides is pretty cool actually.  Now, if you need to add a new shape to the screen you just call one function.  Most of your code doesn’t have to know the details of the shape the user wants to create.  You just call the CreateObject() method passing the shape’s name and you get back a reference to generic shape object that can be stored in any shape container.  The shape container gets passed along and presumably gets a virtual Shape.Draw() method called on all of its contents in a foreach loop.

That’s really awesome until you want to add Triangles to your drawing program.  You probably start by adding a new Triangle.cs class file to your project.  Nice and OOP-y so far.  But then you have to crack open the ShapeName enumeration to add a new identifier for your Triangle class.  Next you have to crack open the switch statement of your ShapeFactory.CreateObject() method to add a case for your new Triangle class.  That’s two violations of the open/closed principle.  That’s not so awesome.  I like making as few changes as possible to existing code when adding features.
You’ll notice that the switch statement is really switching on a type.  That sounds familiar, like I’ve heard that idea before somewhere…  It’s too bad we don’t have virtual constructors, but in the meantime: you could add some static factory methods to the derived Shape classes.  Then, you could replace that switch statement with a map from ShapeNames to ShapeFactory Methods.  You would end up with something like this:

public delegate Shape ShapeFactoryMethod();

 

public class Circle : Shape

{

    public static Shape CreateObject()

    {

        return new Circle();

    }

}

 

public class Square : Shape

{

    public static Shape CreateObject()

    {

        return new Square();

    }

}

 

public class ShapeFactory

{

    private Dictionary<ShapeName, ShapeFactoryMethod> map = new Dictionary<ShapeName, ShapeFactoryMethod>();

 

    public Shape CreateObject(ShapeName shapeName)

    {

        return map[shapeName]();

    }

 

    public void Register(ShapeName shapeName, ShapeFactoryMethod shapeFactoryMethod)

    {

        map.Add(shapeName, shapeFactoryMethod);

    }

 

    public bool Unregister(ShapeName shapeName)

    {

        return map.Remove(shapeName);

    }

}

That’s pretty cool, we got rid of the switch statement.  Now you don’t have to crack open the ShapeFactory.cs file for every additional shape you add, but somewhere you still need to instantiate a ShapeFactory and populate its map with shapes types.  We haven’t solved the problem yet, just moved it:

class Program

{

    static ShapeFactory shapeFactory = new ShapeFactory();

 

    static void CreateShapeFactory()

    {

        shapeFactory.Register(ShapeName.Circle, Circle.CreateObject);

        shapeFactory.Register(ShapeName.Square, Square.CreateObject);

    }

}

We still have two places to change every time we want to add another shape type.  It would be really nice if we could just add a static constructor to each class derived Shape that would automatically register itself with a static ShapeFactory like this:

public class Circle : Shape

{

    static Circle()

    {

        ShapeFactory.Register(ShapeName.Circle, Circle.CreateObject);

    }

 

    public static Shape CreateObject()

    {

        return new Circle();

    }

}

Unfortunately .NET doesn’t play that way.  A class’s Static constructor is not called until the first time a method of that class is called.  To my knowledge, there is nothing in C# that is equivalent to the static scope initialization of C++.  However, there is something C# has that may still be useful: reflection.  In preparation, let’s add a little searchable identifier to each class that’s derived from shape.  Like this:

public class Circle : Shape

{

    public static ShapeName ShapeName

    {

        get { return ShapeName.Circle; }

    }

 

    public static Shape CreateObject()

    {

        return new Circle();

    }

}

Now let’s use a little reflection in the ShapeFactory to automatically load up its map:

public class ShapeFactory

{

    private Dictionary<ShapeName, ShapeFactoryMethod> map = new Dictionary<ShapeName, ShapeFactoryMethod>();

 

    public ShapeFactory()

    {

        Type[] shapeTypes = Assembly.GetAssembly(typeof(Shape)).GetTypes();

 

        foreach (Type shapeType in shapeTypes)

        {

            if (!typeof(Shape).IsAssignableFrom(shapeType) || shapeType == typeof(Shape)) // if (shapeType is not derived from Shape)

            {

                continue; // this type isn’t a Shape type, keep searching through the the assembly

            }

 

            // Get the name of the shape type.

            PropertyInfo propertyInfo = shapeType.GetProperty(“ShapeName”);

            Debug.Assert(propertyInfo != null, “ShapeName property not implemented for shape type: “ + shapeType.Name);

            ShapeName shapeName = (ShapeName)propertyInfo.GetValue(null, null); // shapeName = shapeType.ShapeName;

 

            // Get the static factory method of the shape type.

            MethodInfo methodInfo = shapeType.GetMethod(“CreateObject”);

            Debug.Assert(methodInfo != null, “Factory method not implemented for shape type: “ + shapeType.Name);

            Delegate shapeFactoryMethod = Delegate.CreateDelegate(typeof(ShapeFactoryMethod), methodInfo);

 

            // Automatically register the shape type.

            map.Add(shapeName, (ShapeFactoryMethod)shapeFactoryMethod);

        }

    }

 

    public Shape CreateObject(ShapeName shapeName)

    {

        return map[shapeName]();

    }

}

We just got rid of the need to manually maintain the ShapeFactory’s list of shapes.  Pretty cool so far.  Now, what about that enumeration?  Let’s throw a little more reflection code at the problem:

public class ShapeFactory

{

    private Dictionary<string, ShapeFactoryMethod> map = new Dictionary<string, ShapeFactoryMethod>();

 

    public ShapeFactory()

    {

        Type[] shapeTypes = Assembly.GetAssembly(typeof(Shape)).GetTypes();

 

        foreach (Type shapeType in shapeTypes)

        {

            if (!typeof(Shape).IsAssignableFrom(shapeType) || shapeType == typeof(Shape)) // if (shapeType is not derived from Shape)

            {

                continue; // this type isn’t a Shape type, keep searching through the the assembly

            }

 

            // Get the static factory method of the shape type.

            MethodInfo methodInfo = shapeType.GetMethod(“CreateObject”);

            Debug.Assert(methodInfo != null, “Factory method not implemented for shape type: “ + shapeType.Name);

            Delegate shapeFactoryMethod = Delegate.CreateDelegate(typeof(ShapeFactoryMethod), methodInfo);

 

            // Automatically register the shape type.

            map.Add(shapeType.Name, (ShapeFactoryMethod)shapeFactoryMethod);

        }

    }

 

    public Shape CreateObject(string shapeName)

    {

        return map[shapeName]();

    }

}

So the enumeration is gone AND you can even ditch the ShapeName property attached to each Shape class.  Now, if you want to add a Triangle class all you need to do is drop in your Triangle.cs source file and you won’t have need to modified existing code.  Sweet!  The only thing you have to remember to do is include a CreateObject() method on each new shape.  But wait!  Reflection can help us here too:

public class ShapeFactory

{

    private Dictionary<string, Type> map = new Dictionary<string, Type>();

 

    public ShapeFactory()

    {

        Type[] shapeTypes = Assembly.GetAssembly(typeof(Shape)).GetTypes();

 

        foreach (Type shapeType in shapeTypes)

        {

            if (!typeof(Shape).IsAssignableFrom(shapeType) || shapeType == typeof(Shape)) // if (shapeType is not derived from Shape)

            {

                continue; // this type isn’t a Shape type, keep searching through the the assembly

            }

 

            // Automatically register the shape type.

            map.Add(shapeType.Name, shapeType);

        }

    }

 

    public Shape CreateObject(string shapeName, params object[] args)

    {

        return (Shape)Activator.CreateInstance(map[shapeName], args);

    }

}

Now we don’t have any special requirements of new Shape classes, we’ve ditched the extra factory method delegate, AND we can even use the most appropriate constructor for each object.  The only left to do is turn this factory into a library that works on any class hierarchy.  Let’s make it generic:

public class Factory<Product>

{

    private Dictionary<string, Type> map = new Dictionary<string, Type>();

 

    public Factory()

    {

        Type[] types = Assembly.GetAssembly(typeof(Product)).GetTypes();

 

        foreach (Type type in types)

        {

            if (!typeof(Product).IsAssignableFrom(type) || type == typeof(Product)) // if (type is not derived from Product)

            {

                continue; // this type isn’t a Product type, keep searching through the the assembly

            }

 

            // Automatically register the Product type.

            map.Add(type.Name, type);

        }

    }

 

    public Product CreateObject(string productName, params object[] args)

    {

        return (Product)Activator.CreateInstance(map[productName], args);

    }

}

And this is how we’d use it as a Shape factory:

class Program

{

    static Factory<Shape> shapeFactory = new Factory<Shape>();

 

    static void Main(string[] args)

    {

        Shape s1 = shapeFactory.CreateObject(“Circle”);

        Shape s2 = shapeFactory.CreateObject(“Square”);

    }

}

Now you’ve got a generic factory library in C# …and there’s still plenty of room to trick it out in my next blog post.  In the meantime, you are probably aware that the factory pattern is commonly combined with the singleton pattern.  I would personally recommend this article on the subject: http://www.yoda.arachsys.com/csharp/singleton.html

8 Responses to “A Generic Factory in C#”

  1. Krista Says:

    Oh wow I never knew how to do that without violating the open and close principal. “That’s hot!”

  2. Bookmarks about Type Says:

    [...] – bookmarked by 3 members originally found by relaxdesign on 2008-07-23 A Generic Factory in C# http://tranxcoder.wordpress.com/2008/07/11/a-generic-factory-in-c/ – bookmarked by 3 members [...]

  3. out >> m_Conscientia().toString(); | a multidimensional braindump Says:

    [...] I wanted a factory yesterday I found this method after a little searching, and I like the way it gets you close to the static scope [...]

  4. Chris Says:

    I LOVED this post! Please if you have or know any more of this clever software design please post it.

    My Software guru had been insisting this whole time (in agreement with her other PM chump) that you HAD to scatter case statements all over your code in order to handle creation and use of different types throughout a program.

  5. -arno- Says:

    Hello,
    i developped quite the same thing (~not generic :( ), some time ago, and i’m now facing a new problem with this approach : i want my factory to build an inherited objet declared in a different assembly…the only way i found until now is to make my factory parse every assmebly available in a specific folder in order to find every “type” that would match my object interface… not very clean. Would you have an idea to solve this ?

  6. Bryan Ray Says:

    Definitely a good use of Reflection and an excellent walk through for understanding how to refactor your code and look for “code smells.”

    I would, however, agree with hempelcx and cgassib that you’re very much going towards a Dependency Injection solution. There’s a lot of “support” code there that has to be maintained and rather than focusing on your application you’re having to focus on something that a DI container could do for you.

    Take a look at Ninject, Unity, Autofac, Spring.NET, etc. There’s a handful of good DI libraries out there.

    I only say this for future readers who are looking. Other than that it’s a great article, man.

    Thanks.

Leave a Reply