February
13th,
2018
建立資料模型時,我們可以透過 Data Annotations 的方式來設定該資料模型的資料欄位屬性,藉此增加資料欄位的特性,例如使用 DisplayAttribute
標示該資料欄位要顯示的字樣,在用 ASP.NET MVC 時常透過這樣的方式來設定資料模型,甚至在 Entity Framework 中,也會用這樣的方式來設定欄位屬性,但我們怎樣用程式來抓到這屬性的值呢?
假設我們建立了一個 Student
資料模型如下:
public class Student
{
[Display(Name = "姓名")]
public string Name { get; set; }
[Display(Name = "生日")]
public DateTime Birthday { get; set; }
}
system.componentmodel.dataannotations 這個命名空間提供了很多資料欄位屬性給我們使用,這裡我們透過 DisplayAttribute
指定各個資料欄位要顯示的名稱,例如 Name
的顯示名稱為姓名
,我們可以用下面的程式碼來輕鬆建立一個 Student
物件,並存取該物件的值:
public class Program
{
public static void Main()
{
var obj = new Student()
{
Name = "王大明",
Birthday = DateTime.Now
};
Console.WriteLine(obj.Name);
Console.WriteLine(obj.Birthday);
}
}
這時若要取得該資料模型的資料欄位屬性時,可以先建立一個 Object
的擴充方法,方便我們調用,程式碼如下:
public static class ObjectExtension
{
public static T GetAttributeFrom<T>(this object instance, string propertyName) where T : Attribute
{
var attributeType = typeof(T);
var property = instance.GetType().GetProperty(propertyName);
if (property == null) return null;
return (T)property.GetCustomAttributes(attributeType, false).First();
}
}
這個擴充方法主要的動作如下:
- 使用
GetType()
判斷實體物件的類型,並透過GetProperty()
取得指定的資料欄位(propertyName
) - 如果沒有指定的資料欄位,回傳
null
- 取到指定的資料欄位後,透過
GetCustomAttributes()
取得自訂屬性的陣列,接收以下參數:attributeType
要搜尋的屬性成員的型別inherit
是否透過繼承鏈結一路搜尋到這個屬性成員
注意,這個擴充方法所接受的泛型對象(T
),請限定必須是繼承至 Attribute
的類型。
擴充方法的寫法,可以參考這份官方文件。
如此一來,就可輕鬆使用我們自訂的擴充方法 GetAttributeFrom()
來取得資料欄位的屬性值:
public class Program
{
public static void Main()
{
var obj = new Student()
{
Name = "王大明",
Birthday = DateTime.Now
};
Console.WriteLine(obj.GetAttributeFrom<DisplayAttribute>(nameof(Student.Name)).Name);
Console.WriteLine(obj.Name);
Console.WriteLine(obj.GetAttributeFrom<DisplayAttribute>(nameof(Student.Birthday)).Name);
Console.WriteLine(obj.Birthday);
}
}
Sample Code
Retrieve Data Annotations Gist
以下為針對 Object
和 Type
這兩個類型的擴充方法,方便取用資料模型的屬性設定。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace Extensions | |
{ | |
public static class ObjectExtension | |
{ | |
public static T GetAttributeFrom<T>(this object instance, string propertyName) where T : Attribute | |
{ | |
var attributeType = typeof(T); | |
var property = instance.GetType().GetProperty(propertyName); | |
if (property == null) return default(T); | |
return (T) property.GetCustomAttributes(attributeType, false).FirstOrDefault(); | |
} | |
public static IEnumerable<T> GetAttributeFrom<T>(this object instance) where T : Attribute | |
{ | |
var attributeType = typeof(T); | |
var properties = instance.GetType().GetProperties(); | |
if (properties != null && properties.Length == 0) return default(IEnumerable<T>); | |
return properties?.Select(property => | |
(T) property.GetCustomAttributes(attributeType, false).FirstOrDefault()); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace Extensions | |
{ | |
public static class TypeExtension | |
{ | |
public static T GetAttributeFrom<T>(this Type instance, string propertyName) where T : Attribute | |
{ | |
var attributeType = typeof(T); | |
var property = instance.GetProperty(propertyName); | |
if (property == null) return default(T); | |
return (T) property.GetCustomAttributes(attributeType, false).FirstOrDefault(); | |
} | |
public static IEnumerable<T> GetAttributeFrom<T>(this Type instance) where T : Attribute | |
{ | |
var attributeType = typeof(T); | |
var properties = instance.GetProperties(); | |
if (properties != null && properties.Length == 0) return default(IEnumerable<T>); | |
return properties?.Select(property => | |
(T) property.GetCustomAttributes(attributeType, false).FirstOrDefault()); | |
} | |
} | |
} |
參考資料: