今天在网上看到一个很有用的东西,加上我的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”三个命名空间。