標籤:運算 rgs 讀書 自訂 lin 代碼 訪問 tty sse
(一)在運行期間處理和檢查代碼
自訂特性允許把自訂中繼資料與程式元素關聯起來。反射是一個普通術語,它描述了在運行過程中檢查和處理常式元素的功能。例如,反射允許完成的任務:
- 枚舉類型的成員
- 執行個體化新對象
- 執行對象的成員
- 尋找程式集的資訊
- 檢查應用於某種類型的自訂特性
- 建立和編譯新程式集
(二)自訂特性
使自訂特性非常強大的因素時使用反射,代碼可以讀取這些中繼資料,使用它們在運行期間作出決策。
1、編寫自訂特性
定義一個FieldName特性:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]public class FieldNameAttribute : Attribute{ private string name; public FieldNameAttribute(string name) { this.name = name; }}
(1)AttributeUsage特性
屬性類別本身用一個特性——System.AttributeUsage特性來標記。AttributeUsage第一個參數用於標識自訂特性可以應用到那些類型的程式元素上,其類型是枚舉類型AttrubuteTargets。
當應用類型超過1個時,可以用OR運算子串連:
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
AllowMultiple屬性用於指定該特性是否可以多次應用於同一項上,當設定為false,以下編碼會報錯:
[FieldName("我的屬性1")][FieldName("我的屬性2")]public int MyProperty { get; set; }
Inherited屬性用於指示使用該特性的類或類成員能否由衍生類別或重寫成員繼承。
(2)指定特性參數
編譯器會檢查傳遞給特性的參數,並尋找該特性中帶這些參數的建構函式。一半僅提供一個建構函式,使用屬性來定義任何其他選擇性參數。
(3)指定特性的選擇性參數
另一種文法,可把選擇性參數添加到特性中。這種文法指定選擇性參數的名稱和值,它通過屬性類別中的公用屬性或欄位起作用。例如上述代碼中AttributeUsage特性使用的AllowMultiple和Inherited就是使用的這種文法。
(三)反射
通過System.Type類可以訪問關於任何資料類型的資訊。System.Reflection.Assembly類可以用於訪問給定程式集的相關資訊,或者把這個程式集載入到程式中。
1、System.Type類
Type有與每種資料類型對應的衍生類別。擷取指定任何給定類型的Type引用有3中常用方式:
使用C#的typeof運算子:
Type type = typeof(double);
使用GetType()方法(所有的類都會從System.Object繼承這個方法):
double d = 10.0;Type type = d.GetType();
使用Type類的靜態方法GetType():
Type type = Type.GetType("System.Double");
(1)Type的屬性
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Type intType = typeof(int); 6 Console.WriteLine("當前類型的類型名:"+intType.Name); 7 Console.WriteLine("當前類型的類型完全限定名:" + intType.FullName); 8 Console.WriteLine("當前類型的名稱空間名:" + intType.Namespace); 9 Console.WriteLine("當前類型的直接基類名:" + intType.BaseType);10 Console.WriteLine("當前類型的.NET運行庫中映射到的類型:" + intType.UnderlyingSystemType);11 Console.WriteLine("是否為數組的:" + intType.IsArray);12 Console.WriteLine("是否為實值型別:" + intType.IsValueType);13 }14 }15 public class MyBaseClass { }16 public class MyClass : MyBaseClass { }
運行以上代碼,結果如下:
還有很多IsXXX來判斷是否為某種類型。
(2)方法
System.Type類的大多數方法都用於擷取對應資料類型的成員資訊:建構函式、屬性、方法和事件。尾碼加‘s’的表示擷取當前資料類型中所有的成員相關資訊,不加則只擷取資料類型中一個成員的相關資訊。
Type intType = typeof(int);var method = intType.GetMethod("GetHashCode");var methods = intType.GetMethods();foreach (var item in methods){}
System.Type類還包含有GetConstructor()方法和GetConstructors()等。
2、Assembly類
Assembly類在System.Reflection名稱空間中定義,它允許訪問給定程式集的中繼資料,它也包含可以載入和執行程式集(假定該程式集是可執行檔)的方法。可以使用靜態成員Assembly.Load()或Assembly.LoadFrom()。
使用Load()載入:
Assembly assembly1 = Assembly.Load("程式集名");
使用LoadFrom()載入:
Assembly assembly2 = Assembly.LoadFrom("程式集實際路徑");
載入程式集後就可以使用它的各種屬性進行查詢:
string name = assembly1.FullName;
(1)擷取在程式集中定義的類型的詳細資料
Assembly類的一個功能是它可以獲得在相應程式集中定義的所有類型的詳細資料,只要調用Assembly.GetTypes()方法,就可以返回一個包含所有類型的詳細資料的System.Type引用數組。
Type[] typeArray = assembly.GetTypes();
(2)擷取自訂特性的詳細資料
如果要確定程式集從整體上關聯了什麼自訂特性,就需要調用Attribute類的一個靜態方法GetCustomAttributes()。
Attribute[] definedAttributes = Attribute.GetCustomAttributes(assembly);
【讀書筆記】C#進階編程 第十五章 反射