反射-Description-Level1

探討attribute

一、前言
相信很多程式開發人員都有碰過,在專案的某些類別(class)或是列舉(enum)中都有像下圖一樣的寫法
這種寫法像是metadata,也就是程式的「資料標記」,至於這種寫法的用途很廣,有空再根據自已所知的再舉例
這篇只介紹如何取得Description的內容,因為自已也是在摸索這種寫法的功用,後續會把自已的心得一個一個寫下來

圖1.1

二、Description類別
Description其實就是DescriptionAttribute,繼承Attribute(圖2.1),所以Description很多特性都是來自已attribute,簡單來說就是Attribute的擴充
而當你使用像下面的code,其實就是將值指給DescriptionAttribute中的Description屬性

[Description("學生姓名")]



圖2.1

 

三、取得Desctipon的內容
這邊以class跟enum為例
1.class
    (1)先撰寫一個student的class,並加上class、屬性、方法的description(圖3.1)
圖3.1
    (2)分別取得class、屬性、方法的Description
         要取得這三者的Description,首先要了解type、PropertyInfo、MethodInfo,這三個類別都有一個GetCustomAttributes的function,就是透過它來取得 
         a.取得class的Description-->用type的GetCustomAttributes
             

//取得目標物件的type
			Type oType = typeof(Student);

			//取得類別的description
			object[] classAttrs = oType.GetCustomAttributes(true);
			foreach (var attr in classAttrs)
			{
				DescriptionAttribute da = attr as DescriptionAttribute;
				if (da != null)
				{
					Console.WriteLine(da.Description);
				}
			}


         b.取得屬性的Description-->用PropertyInfo的GetCustomAttributes

//取得屬性的description
			PropertyInfo[] props = oType.GetProperties();

			foreach (var prop in props)
			{
				object[] attrs = prop.GetCustomAttributes(true);

				foreach (var attr in attrs)
				{
					DescriptionAttribute da = attr as DescriptionAttribute;
					if (da != null)
					{
						Console.WriteLine(da.Description);
					}

				}
			}


         c.取得方法的Description-->用MethodInfo的GetCustomAttributes

//取得方法的description
			MethodInfo[] oMethodInfos = oType.GetMethods();

			foreach (var method in oMethodInfos)
			{
				object[] methodAttrs = method.GetCustomAttributes(true);
				foreach (var attr in methodAttrs)
				{
					DescriptionAttribute da = attr as DescriptionAttribute;
					if (da != null)
					{
						Console.WriteLine(da.Description);
					}
				}
			}

2.enum
(1)先撰寫一個ClassRoom的enum,並加上enum跟其成員的Description(圖3.2)
圖3.2
  (2)分別取得enum跟成員的Description
       要取得這兩者的Description,首先要了解Type跟FieldInfo,這兩個類別都有一個GetCustomAttributes的function,就是透過它來取得 
        a.取得enum的Description-->用type的GetCustomAttributes
 

//取得enum的description
			var type = typeof(ClassRoom);
			if (!type.IsEnum) throw new InvalidOperationException();
			
			object[] enumTypeDesc = type.GetCustomAttributes(true);
			foreach (var desc in enumTypeDesc)
			{
				if (desc.GetType() == typeof(DescriptionAttribute))
				{
					var transDesc = (DescriptionAttribute)desc;
					System.Console.WriteLine(transDesc.Description);
				}
			}


        b.取得成員的Description-->用FieldInfo的GetCustomAttributes
 

//取得成員(member)的description
			foreach (var field in type.GetFields())
			{
				object[] enumMemberDesc = field.GetCustomAttributes(true);
				foreach (var desc in enumMemberDesc)
				{
					if (desc.GetType() == typeof(DescriptionAttribute))
					{
						var transDesc = (DescriptionAttribute)desc;
						System.Console.WriteLine(transDesc.Description);
					}
				}
			}

 

三、總結
其實這篇的程式重點應該在於type、PropertyInfo、MethodInfo、FieldInfo,依照名稱可以整理成下表,比較需要注意的大概就是
GetCustomAttributes(true),設true會跟該類別的繼承有關,不過目前不會有繼承的或是被繼承的類別,所以true或false不會有影響
後續再研究該參數的用意
MSDN:type

type 類別  
PropertyInfo 屬性 透過type的GetProperties()
MethodInfo 方法 透過type的GetMethods()
FieldInfo 欄位 透過type的GetFields()