I recently was searching for some ideas for creating an object factory to centralize the creation of various class instances. I came across several interesting articles on the topic related to C# and .NET development. One in particular on The Code Project site caught my attention. I would like to thank Rob Hemstede for his Generic Object Factory article which was my inspiration for this post.
This one was my initial inspiration for this post but they all lacked one thing. They were specific to individual types or families of objects.
One way of implementing a generic object factory in .NET is to use the Activator class. This can be accomplished with something like the following:
var type = Type.GetType("Namespace.Class, Assembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); var instance = Activator.CreateInstance(type);
I worked with this approach on a previous .NET 2.0 WinForms project. It leveraged the User Interface Process (UIP) Application Block from Microsoft’s Patterns and Practices site. The UIP block instantiated the views using a model-view-controller (MVC) pattern. This worked well and was robust. Although with this object factory I did not have the requirement of defining customized views at runtime through configuration. With that in mind I decided to take another approach in the design.
One thing I noticed with the various .NET examples I found was that each factory was specific to a single type or family of types. I wanted something that could be used to create various types of objects. In the past I had accomplished this type of functionality in C++ using function pointers. This approach led me to the following ObjectFactory class.
public class ObjectFactory { private SortedList<string, object> _factories = new SortedList<string, object>(); public void RegisterFactory<TR>(Func<TR> factory) { Add<TR>(factory); } public void RegisterFactory<T1, TR>(Func<T1, TR> factory) { Add<TR>(factory); } private void Add<TR>(object factory) { if (!_factories.ContainsKey(typeof(TR).FullName)) _factories.Add(typeof(TR).FullName, factory); } public TR Create<TR>() where TR : new() { return new TR(); } public TR Create<T1, TR>(T1 t1) { object factory; if (_factories.TryGetValue(typeof(TR).FullName, out factory)) ((Func<T1, TR>)factory).Invoke(t1); return default(TR); } }
Here is a simple example that demonstrates the usage of the ObjectFactory.
class Program { static void Main(string[] args) { var factories = new ObjectFactory(); factories.RegisterFactory<int, ITestObject>(id => new TestObject(id)); var testObj = factories.Create<int, ITestObject>(1); Console.WriteLine(@"ITestObject instance created with Id=" + testObj.Id); Console.ReadLine(); } }