程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> Effective C#原則42:使用特性進行簡單的反射(2)

Effective C#原則42:使用特性進行簡單的反射(2)

編輯:關於C語言

現在,讓我們添加另一個 新的特性來查找命令句柄。一個類型應該可以很簡單的實現好幾個命令句柄,所 以你可以定義新的特性,讓插件的作者可以把它添加到命令句柄上。這個特性會 包含一參數,這些參數用於定義新的菜單命令應該放在什麼地方。每一個事件句 柄處理一個特殊的命令,而這個命令應該在菜單的某個特殊地方。為了標記一個 命令句柄,你要定義一個特性,用於標記一個屬性,讓它成為一個命令句柄,並 且申明菜單上的文字以及父菜單文字。DynamicCommand特性要用兩個參數來構造 :菜單命令文字以及父菜單的文字。這個特性類還包含一個構造函數,這個構造 函數用於為菜單初始化兩個字符串。這些內容同樣可以使用可讀可寫的屬性:

[AttributeUsage( AttributeTargets.Property ) ]
public class DynamicMenuAttribute : System.Attribute
{
  private string _menuText;
 private string _parentText;
  public DynamicMenuAttribute( string CommandText,
  string ParentText )
 {
  _menuText = CommandText;
   _parentText = ParentText;
 }
 public string MenuText
 {
  get { return _menuText; }
  set { _menuText = value; }
 }
 public string ParentText
 {
   get { return _parentText; }
  set { _parentText = value; }
 }
}

這個特性類已經做了標記,這樣它只能被應用到屬 性上。而命令句柄必須在類中以屬性暴露出來,用於提供給命令句柄來訪問。使 用這一技術,可以讓程序在啟動的時候查找和添加命令句柄的代碼變得很簡單。

現在你創建了這一類型的一個對象:查找命令句柄,以及添加它們到新 的菜單項中。你可以把特性和反射組合起來使用,用於查找和使用命令句柄屬性 ,對對象進行推測:

// Expanded from the first code sample:
// Find the types in the assembly
foreach( Type t in asm.GetExportedTypes( ) )
{
 if (t.GetCustomAttributes(
  typeof( CommandHandlerAttribute ), false).Length > 0 )
 {
  // Found a command handler type:
  ConstructorInfo ci =
   t.GetConstructor( new Type[0] );
  if ( ci == null ) // No default ctor
   continue;
  object obj = ci.Invoke( null );
  PropertyInfo [] pi = t.GetPropertIEs( );
  // Find the propertIEs that are command
  // handlers
  foreach( PropertyInfo p in pi )
  {
    string menuTxt = "";
   string parentTxt = "";
   object [] attrs = p.GetCustomAttributes(
    typeof ( DynamicMenuAttribute ), false );
   foreach ( Attribute at in attrs )
   {
     DynamicMenuAttribute dym = at as
      DynamicMenuAttribute;
    if ( dym != null )
     {
     // This is a command handler.
     menuTxt = dym.MenuText;
     parentTxt = dym.ParentText;
      MethodInfo mi = p.GetGetMethod();
     EventHandler h = mi.Invoke( obj, null )
      as EventHandler;
      UpdateMenu( parentTxt, menuTxt, h );
    }
   }
  }
 }
}
private void UpdateMenu( string parentTxt, string txt,
 EventHandler cmdHandler )
{
  MenuItem menuItemDynamic = new MenuItem();
  menuItemDynamic.Index = 0;
 menuItemDynamic.Text = txt;
  menuItemDynamic.Click += cmdHandler;
 //Find the parent menu item.
 foreach ( MenuItem parent in mainMenu.MenuItems )
  {
  if ( parent.Text == parentTxt )
  {
    parent.MenuItems.Add( menuItemDynamic );
   return;
   }
 }
 // Existing parent not found:
 MenuItem newDropDown = new MenuItem();
 newDropDown.Text = parentTxt;
 mainMenu.MenuItems.Add( newDropDown );
  newDropDown.MenuItems.Add( menuItemDynamic );
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved