Visual Studio .NET 2002Visual C++ 7.0.NET 1.0Windows 2000Windows XP中级开发Visual StudioWindowsC++.NETC#
另一个类工厂
基于C#事件和委托的类工厂。
引言
我遇到了需要一个类工厂的情况,它可以创建各种对象的实例,并且足够灵活以支持工厂未知的类。我开始寻找这样的解决方案,但令人惊讶的是没有找到(尽管我找到很多“类工厂文章”)。在我的搜索过程中,我发现了一篇文章由 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
}