Skip to content

C# Generic Factory

by Alex Peck on March 7th, 2009

Since I tend to think in C++, I’ve found that I program C# with a C++ accent (as I realised when I read C# in depth). In C++, the Loki library provides a solid foundation for most patterns I use (I started out with patterns after reading the excellent Modern C++ Design). I assumed that a similar library must exist for C# generics, but as yet haven’t found it.

When 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 initialisation of C++. I also like the fact that you don’t have to do anything special to use different constructors, and you can use the Type type instead of generating GUIDs to identify types COM style. I have two minor observations, however. Firstly, if you have a class hierarchy that spans multiple assemblies, the example code will miss some objects. Secondly, the ctor collects abstract types, which seems a little wasteful since you can’t instantiate them. So here’s my contribution:

    public class Factory<Product>
    {
        private Dictionary<string, Type> map = new Dictionary<string, Type>();
 
        public Factory()
        {
            // Evaluate all types in all assemblies loaded by the current app
            Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
 
            foreach (Assembly assembly in assemblies)
            {
                Type[] types = assembly.GetTypes();
 
                foreach (Type type in types)
                {
                    // if Type is not derived from Product Type skip it and continue searching
                    if (!typeof(Product).IsAssignableFrom(type) || type == typeof(Product) || type.IsAbstract)
                    {
                        continue;
                    }
 
                    this.map.Add(type.Name, type);
                }
            }
        }
 
        public Product CreateObject(string type, params object[] args)
        {
            return (Product)Activator.CreateInstance(this.map[type], args);
        }
     }

At this point I was relatively pleased. Then in a code review a colleague pointed out my C++ accent (why did you call the dictionary a map? – because I copied and pasted), and suggested that with reflection you shouldn’t need to store such a map. I played around for about half an hour and couldn’t find an efficient way to do the type look up from a string (which is not to say that it’s impossible). I think if you need to evaluate types in all the loaded assemblies it’s probably going to be a relatively expensive operation, and you therefore want to cache the result.

The next thing to fix/handle is the possibility of name collisions when you define types in different namespaces.

3 Comments
  1. Hi, cool post. I have been was looking for something similar so thanks for writing.

  2. Hi, very nice post. Thanks.

  3. I really like your post. Is it copyright protected?

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS