一說到可擴充結構,大家立即想到外掛程式,想到嚴謹的結構設計,複雜的程式,眾多的介面。確實,很多大型複雜的程式都實現了可擴充結構,這是為了方便使用者自己擴充這些程式。但一般的這種結構比較複雜,實現起來比較麻煩。以下是實現一個簡單的可擴充結構的例子。/// <summary>
/// 動作基礎類
/// </summary>
public abstract class ActionBase
{
/// <summary>
/// 動作名稱
/// </summary>
public abstract string Name{ get;}
/// <summary>
/// 執行動作
/// </summary>
public abstract void Execute();
}
/// <summary>
/// 動作集合
/// </summary>
public class ActionList : System.Collections.CollectionBase
{
/// <summary>
/// 註冊動作
/// </summary>
/// <param name="a"></param>
public void Registe( ActionBase a )
{
this.InnerList.Add( a );
}
/// <summary>
/// 獲得指定名稱的動作
/// </summary>
public ActionBase this[ string name ]
{
get
{
foreach( ActionBase a in this.InnerList )
{
if( a.Name == name )
return a ;
}
return null;
}
}
/// <summary>
/// 指定指定名稱的動作
/// </summary>
/// <param name="name">動作名稱</param>
public void Execute( string name )
{
ActionBase a = this[ name ];
if( a != null )
a.Execute();
}
}//public class ActionList : System.Collections.CollectionBase
internal class MyAction1 : ActionBase
{
public override string Name
{
get{ return "action1";}
}
public override void Execute()
{
System.Console.WriteLine( "Action1 execute");
}
}
internal class MyAction2 : ActionBase
{
public override string Name
{
get{ return "action2";}
}
public override void Execute()
{
System.Console.WriteLine( "Action2 execute");
}
}
public class StartApplication
{
public static void Main()
{
ActionList list = new ActionList();
list.Registe( new MyAction1());
list.Registe( new MyAction2());
list.Execute("action1");
}
}//public class StartApplication
從上面的例子可以看出,實現一個可擴充結構需要很多類來支援。在很多情況下,我們只是需要簡單的可擴充結構,而這種實現方式也太複雜臃腫了。
有時可以使用反射來實現簡單的可擴充結構,例如微軟.NET架構下的System.Xml.Xsl.XslTransform內部就使用了反射來實現對XSLT函數的擴充。但反射可能存在安全和效能問題,而且存在不方便調試的情況。
在此我提出使用委託來實現簡單的可擴充結構。委託效能比反射好,安全而且便於調試。其例子為
/// <summary>
/// 定義委託類型
/// </summary>
public delegate void ActionMethodDelegate();
/// <summary>
/// 動作集合
/// </summary>
public class ActionList2
{
private System.Collections.Hashtable myTable = new System.Collections.Hashtable();
/// <summary>
/// 註冊動作
/// </summary>
/// <param name="name">動作名稱</param>
/// <param name="targe">方法</param>
public void Registe( string name , ActionMethodDelegate targe )
{
myTable[ name ] = targe ;
}
/// <summary>
/// 執行指定名稱的動作
/// </summary>
/// <param name="name">動作名稱</param>
public void Execute( string name )
{
ActionMethodDelegate targe = myTable[ name ] as ActionMethodDelegate ;
if( targe != null )
targe();
}
}
public class FunctionClass
{
public static void Action1()
{
System.Console.WriteLine( "Action1 execute");
}
public static void Action2()
{
System.Console.WriteLine("Action2 execute");
}
}
public class StartApplication2
{
public static void Main()
{
ActionList2 list = new ActionList2();
list.Registe( "action1" , new ActionMethodDelegate( FunctionClass.Action1 ));
list.Registe( "action2" , new ActionMethodDelegate( FunctionClass.Action2 ));
list.Execute( "action2");
}
}
從上面的例子可以看出,使用委託來實現簡單的可擴充結構,代碼量和類的數量大大減少,而且擴充起來非常容易,只要實現某個靜態函數,然後調用Registe函數註冊一下就可以了。
對於有些按照名稱調用功能的程式結構,一般的是使用switch-case結構來實現,現在可以考慮使用這種委託的可擴充結構,避免大型的switch-case語句,添加和刪除功能比較方便,有利於函數的相互獨立,而且便於擴充。
由於委託能接受參數,因此可以使用委託來實現稍微複雜的可擴充結構,但對於比較複雜功能強的可擴充結構,委託可能還不夠,還得使用老辦法。
XDesigner軟體工作室( http://www.xdesigner.cn ) 2006-9-15