Introduction
I came across the need for a class factory that can create instances of a
wide range of objects, which will be flexible enough to support classes that are
unknown to the factory. I started skimming for such a solution but surprisingly
none was found (all though I found a lot of "Class Factory articles"). During my
search I found an article wrote by Chris Sells that explains events &
delegates .NET Delegates: A C# Bedtime Story.
This article gave me the idea to use the events mechanism to broadcast a
request for a new instance, any listener that feels that he is the right creator
can create a instance and return it.
Using the code
In order to use the ClassFactory add a reference to ClassFactory.dll
to your project. In the class that needs to be created with the
Factory add a static method with the following signature:
public class A
{
public static void Creator(object sender,
Yoramo.ClassFactory.CreateObjectArgs e)
{
if (e._Key == "A" && e._CreatedObject == null)
e._CreatedObject = new A() ;
}
}
Create an instance of the factory (you can derive it and modify it to be a
singleton if you like).
Yoramo.ClassFactory.ClassFactory aFactory =
new Yoramo.ClassFactory.ClassFactory() ;
Add the class's delegator method to the factory.
aFactory.CreateIt += new Yoramo.ClassFactory.CreateObjectEvent(
A.Creator) ;
aFactory.CreateIt += new Yoramo.ClassFactory.CreateObjectEvent(
B.Creator) ;
aFactory.CreateIt += new Yoramo.ClassFactory.CreateObjectEvent(
C.Creator) ;
Now you can call the create method with a string as a parameter and one of
your classes can respond with a new instance.
object aObj = aFactory.Create("A") ;
Drawbacks
I could not find a way to stop the broadcasting in case that any
creator has created the needed instance, all the other listeners that are in the
list will continue receiving the event even though the request has been
fulfilled. Because of that they need politely to return immediately. This
behavior enables a creator to overwrite the product of a previous creator (which
is not a desired behaviour).
With the help of 'pbackhuvud' I have modified the code to
overcome the broadcasting problem. Here is the final result
public object Create(string iKey)
{
CreateObjectArgs aArgs = new CreateObjectArgs(iKey) ;
if (CreateIt != null)
{
foreach (CreateObjectEvent Handler in
CreateIt.GetInvocationList())
{
try
{
if (aArgs._CreatedObject == null)
Handler(this,aArgs) ;
else
break ;
}
catch (Exception ex)
{
System.Diagnostics.Debug.Assert(false,
"A Creator as raised an exception !!!") ;
}
}
}
return aArgs._CreatedObject ;
}
The Code
using System;
namespace Yoramo.ClassFactory
{
public delegate void CreateObjectEvent(object iSender,
CreateObjectArgs e) ;
public class ClassFactory
{
public event CreateObjectEvent CreateIt ;
public object Create(string iKey)
{
CreateObjectArgs aArgs = new CreateObjectArgs(iKey) ;
if (CreateIt != null)
CreateIt(this,aArgs) ;
return aArgs._CreatedObject ;
}
}
#region EventArgs derive class
public class CreateObjectArgs : EventArgs
{
public CreateObjectArgs (string iKey)
{
_Key = iKey ;
_CreatedObject = null ;
}
public string _Key ;
public object _CreatedObject ;
}
#endregion
}