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

Effective C#原則43:請勿濫用反射(1)

編輯:關於C語言

創建二進制的組件時,同時也意味著你要使用遲後綁定和反射來查找你所須 要的具有特殊功能代碼。反射是一個很有力的工具,而且它讓你可以寫出可動態 配置的軟件。使用反射,一個應用程序可以通過添加新的組件來更新功能,而這 些組件是在軟件最開始發布時沒有的。這是有利的。

這一伸縮性也帶來 了一些復雜的問題,而且復雜問題的增加又會增加出現其它問題的可能。當你使 用反射時,你是圍繞著C#的安全類型。然而,成員調用的參數和返回值是以 System.Object類型存在的。你必須在運行時確保這些類型是正確的。簡單的說 ,使用反射可以讓創建動態的程序變得很容易,但同時也讓程序出現錯誤變得很 容易。通常,簡單的思考一下,你就可以通過創建一系列接口集合來最小化或者 移除反射,而這些接口集合應該表達你對類型的假設。

反射給了你創建 類型實例的功能,以及在對象上調用成員方法,以及訪問對象上的成員數據。這 聽上去就跟每天的編程任務是一樣的。確實是這樣的,對於反射,並沒有什麼新 奇的:它就是動態創建其它的二進制組件。大多數情況下,你並不須要像反射這 樣的伸縮功能,因為有其它可選的更易維護的方案。

讓我們從創建一個 給定類型的實例開始,你可以經常使用一個類廠來完成同樣的任務。考慮下面的 代碼,它通過使用反射,調用默認的構造函數創建了一個MyType 的實例:

// Usage:Create a new object using reflection:
Type t = typeof( MyType );
MyType obj = NewInstance( t ) as MyType;
// Example factory function, based on Reflection:
object NewInstance( Type t )
{
 // Find the default constructor:
 ConstructorInfo ci = t.GetConstructor( new Type[ 0 ] );
 if ( ci != null )
  // Invoke default constructor, and return
  // the new object.
  return ci.Invoke( null );
 // If it failed, return null.
 return null;
}

代碼通過反射檢測了類型,而且調用了默認的構造函數來創建了 一個對象。如果你須要在運行時創建一個預先不知道任何信息的類型實例,這是 唯一的選擇。這是一段脆弱的代碼,它依懶於默認的構造函數的存在。而且在你 移除了MyType類型的默認構造函數時仍然是可以通過編譯的。你必須在運行時完 成檢測,而且捕獲任何可能出現的異常。一個完成同樣功能的類廠函數,在構造 函數被移除時是不能通過編譯的:

public MyType NewInstance( )
{
 return new MyType();
}

(譯注:其實 VS.Net會給我們添加默認的構造函數,所以上面的兩個方法都是可以編譯,而且 可以正確運行的。本人做過測試。但如果給構造函數添加訪問限制,那麼可以讓 類廠無法構造對象而產生編譯時錯誤。)

你應該使用靜態的類廠函數來取 代依懶於反射的實例創建方法。如果你須要實例對象使用遲後數據綁定,那麼應 該使用類廠函數,而且使用相關的特性來標記它們(參見原則42)。

另一 個反射的潛在的用處就是訪問類型的成員。你可以使用成員名和類型在運行時來 調用實際的函數:

// Example usage:
Dispatcher.InvokeMethod( AnObject, "MyHelperFunc" );
// Dispatcher Invoke Method:
public void InvokeMethod ( object o, string name )
{
 // Find the member functions with that name.
 MemberInfo[] myMembers = o.GetType( ).GetMember( name );
 foreach( MethodInfo m in myMembers )
 {
  // Make sure the parameter list matches:
  if ( m.GetParameters( ).Length == 0 )
   // Invoke:
   m.Invoke( o, null );
 }
}

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