Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Another class factory

0.00/5 (No votes)
3 May 2003 1  
Class Factory based on C# events & delegate

Sample Image - AnotherClassFactory.jpg

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:

/// Class A will be created with the ClassFactory 

/// so it has a static metod.

/// this method will be use as a event handler.

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") ; // create an object with Key="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) ; // try to create the object.

        else
           break ;  // the instance has been created. 

                    // stop the serch for a creator.

       } 
       catch (Exception ex)
           {
        System.Diagnostics.Debug.Assert(false,
                   "A Creator as raised an exception !!!") ;
       }
    }
   }
   return aArgs._CreatedObject ;
}

The Code

using System;

namespace Yoramo.ClassFactory
{
    /// <SUMMARY>

    /// delegator for ClassFactory create.

    /// </SUMMARY>

    public delegate void CreateObjectEvent(object iSender, 
           CreateObjectArgs e) ;

    /// <SUMMARY>

    /// Summary description for ClassFactory.

    /// </SUMMARY>

    public class ClassFactory
    {
        /// <SUMMARY>

        /// Declare the Event

        /// </SUMMARY>

        public event CreateObjectEvent CreateIt ; 

        /// <SUMMARY>

        /// Try to create a instance of a class 

        /// that recognize the key "iKey"

        /// </SUMMARY>

        ///  string value that indicates the needed class

        /// <RETURNS>object - The istance created or 

        /// null if no instance was created</RETURNS>

        public object Create(string iKey)
        {
            CreateObjectArgs aArgs = new CreateObjectArgs(iKey) ;
            if (CreateIt != null)
               CreateIt(this,aArgs) ;

            return aArgs._CreatedObject ;
        }
    }

    #region EventArgs derive class
    /// <SUMMARY>

    /// Summary description for CreateObjectArgs.

    /// A derivation of EventArgs.

    /// Additional information:

    ///        - _Key - The Key that specifie the nequested class

    ///        - _CreatedObject - The object instance that 

    ///                  was created (return value)

    ///            

    ///    The factory class will create a instance of 

    ///    this EventArgs derivation and 

    ///    initialize the _Key member. This inctance will 

    ///    be passed to the event and

    ///    the result will be in the  _CreatedObject member.

    /// </SUMMARY>

    public class CreateObjectArgs : EventArgs
    {
        /// <SUMMARY>

        /// Constractor

        /// </SUMMARY>

        /// string value, use it as a key

        public CreateObjectArgs (string iKey)
        {
            _Key = iKey ;
            _CreatedObject = null ;
        }
        /// <SUMMARY>

        /// Identification key for the instance class.

        /// </SUMMARY>

        public string _Key ;
        /// <SUMMARY>

        /// Return the new instance in this member

        /// </SUMMARY>

        public object _CreatedObject ;
    }
    #endregion
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here