65.9K
CodeProject 正在变化。 阅读更多。
Home

另一个类工厂

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.67/5 (9投票s)

2003年5月4日

CPOL

2分钟阅读

viewsIcon

75129

downloadIcon

666

基于C#事件和委托的类工厂。

Sample Image - AnotherClassFactory.jpg

引言

我遇到了需要一个类工厂的情况,它可以创建各种对象的实例,并且足够灵活以支持工厂未知的类。我开始寻找这样的解决方案,但令人惊讶的是没有找到(尽管我找到很多“类工厂文章”)。在我的搜索过程中,我发现了一篇文章由 Chris Sells 撰写,解释了事件和委托 .NET Delegates: A C# Bedtime Story.

这篇文章给了我一个想法,使用事件机制来广播一个新实例的请求,任何认为自己是正确创建者的监听器都可以创建一个实例并返回它。

使用代码

为了使用 ClassFactory,请将引用添加到 ClassFactory.dll 到你的项目中。在需要使用工厂创建的类中,添加一个具有以下签名的静态方法

/// 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() ;
    }
}

创建一个工厂实例(你可以继承它并修改它以使其成为单例,如果你愿意)。

Yoramo.ClassFactory.ClassFactory aFactory = 
    new Yoramo.ClassFactory.ClassFactory() ;

将类的委托方法添加到工厂。

aFactory.CreateIt += new Yoramo.ClassFactory.CreateObjectEvent(
    A.Creator) ;
aFactory.CreateIt += new Yoramo.ClassFactory.CreateObjectEvent(
    B.Creator) ;
aFactory.CreateIt += new Yoramo.ClassFactory.CreateObjectEvent(
    C.Creator) ;

现在你可以使用字符串作为参数调用 create 方法,并且你的类之一可以响应并返回一个新的实例。

object aObj = aFactory.Create("A") ; // create an object with Key="A"

缺点

我找不到一种方法来停止广播,以防任何创建者已经创建了所需的实例,列表中的所有其他监听器将继续接收事件,即使请求已经得到满足。因此,他们需要礼貌地立即返回。 这种行为允许一个创建者覆盖先前创建者的产品(这不是期望的行为)。

在 'pbackhuvud' 的帮助下,我已经修改了代码以克服广播问题。 这是最终结果

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 ;
}

代码

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
}
© . All rights reserved.