今天在网上看到一个很有用的东西,加上我的blog里面什么也没有,所以就拷贝过来装门面。
原文地址:点晴工作室 作者:梁利锋
有时候,我们经常需要处理一些比较大的 switch 语句,如:
public interface IAction { void DoAction(string ActionName); } public class OkCancelAction : IAction { public void DoAction(string ActionName) { switch( ActionName ) { case "OK": Console.WriteLine("OK Action raised."); break; case "CANCEL": Console.WriteLine("CANCEL Action raised."); break; default: throw new Exception("ActionName Not Defined."); } } } 一般的,如果这个 switch 比较大,可以使用如下的方法进行分发:
public interface IAction { void DoAction(string ActionName); }
public class OkCancelAction : IAction { public void DoAction(string ActionName) { switch( ActionName ) { case "OK": Ok_Clicked(); break; case "CANCEL": Cancel_Clicked(); break; default: throw new Exception("ActionName Not Defined."); } }
private void Ok_Clicked() { Console.WriteLine("OK Action raised."); }
private void Cancel_Clicked() { Console.WriteLine("CANCEL Action raised."); } } 不过在使用了反射之后,以上的分发方法还可以进一步封装,以便在写真正的 Action 类的时候非常简单。当然,反射还是和自定义属性结合才能进行更精确的定制:
[AttributeUsage(AttributeTargets.Method)] public class ActionMethodAttribute : Attribute { public string ActionName;
public ActionMethodAttribute(string ActionName) { this.ActionName = ActionName; } } 另外,定义一个自定义的异常:
public class ActionNameNotDefinedException : Exception { public ActionNameNotDefinedException() : base("行动名未定义") {} public ActionNameNotDefinedException(string ErrorMessage) : base(ErrorMessage) {} } 然后是最重要的 ActionBase 类:
public abstract class ActionBase { private Hashtable ht = new Hashtable(); // Hashtable 没有保存顺序特征,所以加入这一个 ArrayList private ArrayList al = new ArrayList();
public string [] GetActionNames() { return (string[])al.ToArray(typeof(string)); }
public ActionBase() { Console.WriteLine(this.ToString()); Type t = this.GetType(); foreach ( MethodInfo mi in t.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic) ) { ActionMethodAttribute[] mis = (ActionMethodAttribute[])mi.GetCustomAttributes(typeof(ActionMethodAttribute), false); if ( mis != null && mis.Length > 0 ) { string ActionName = mis[0].ActionName; al.Add( ActionName ); ht.Add( ActionName, mi ); } } }
public void DoAction(string ActionName) { if ( ht.Contains( ActionName ) ) { ((MethodInfo)ht[ActionName]).Invoke(this, new object[] {}); } else { throw new ActionNameNotDefinedException(); } } } 然后,定义真正的 Action 类就很简单了:
public class OkCancelAction : ActionBase { [ActionMethod("OK")] private void Ok_Clicked() { Console.WriteLine("OK Action raised."); }
[ActionMethod("CANCEL")] private void Cancel_Clicked() { Console.WriteLine("CANCEL Action raised."); } } 调用运行如下所示:
class ApplicationEntry { [STAThread] static void Main(string[] args) { Console.WriteLine("/////////////////////////////////////"); ActionBase a = new OkCancelAction();
Console.WriteLine("/////////////////////////////////////"); string [] ss = a.GetActionNames(); Console.WriteLine( string.Join("\r\n",ss) );
Console.WriteLine("/////////////////////////////////////"); foreach ( string s in ss ) { a.DoAction(s); }
Console.WriteLine("/////////////////////////////////////"); Console.ReadLine(); } } 要注意的是,要编译运行的话,需要加入“System”、“System.Collections”和“System.Reflection”三个命名空间。
|