中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档 | 网通镜像
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > .NET > 临时文章
使用反射分发 switch 操作
作者:未知 时间:2004-12-02 12:12 出处:Blog 责编:chinaitpower
              摘要:暂无
今天在网上看到一个很有用的东西,加上我的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”三个命名空间。
关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有