- 目前在 MVC 與 WEB API 中,都有大量地使用 Attribute,需要了解此使用的方法
- Attribute
- 編譯期進行初始化,而不是執行期
- 用於在運行時傳遞程序中各種元素 (比如類別,方法,結構... 等等)的行為訊息聲明
- 提供三種預定特性:
- AttributeUsage
- Conditional
- Obsolete
- Effective C# 此書中有提到:
- 推建使用 Conditional attribute (條件特性)
- 因 #if/#endif 容易被濫用,使得編寫程式難於理解且更難於變更
- 編譯時會依據指定的值(Debug / Trace),所產生的 IL 比使用 #if/#endif 更有效率
[Conditional("DEBUG")]
Using Conditional
- Conditional Code:主要在 DEBUG 才會執行時間測試
public static class ConditionalLib
{
static Stopwatch stopwatch = new Stopwatch();
[Conditional("DEBUG")]
public static void StartLog()
{
stopwatch = Stopwatch.StartNew();
}
[Conditional("DEBUG")]
public static void StopLog()
{
stopwatch.Stop();
Console.WriteLine("Elapsed:{0} ", stopwatch.Elapsed);
}
}
static void Main(string[] args)
{
long sum = 0;
Console.WriteLine("Loop 1,000,000");
ConditionalLib.StartLog();
for (int i = 0; i <= 1000000; i++ )
{
sum += i;
}
ConditionalLib.StopLog();
Console.WriteLine("Loop 2,000,000");
ConditionalLib.StartLog();
sum = 0;
for (int i = 0; i <= 2000000; i++)
{
sum += i;
}
ConditionalLib.StopLog();
}
- Obsolete 屬性裝飾的型別或成員,編譯器將會發出警告或錯誤。
public class ObsoleteLib
{
[Obsolete]
public void GetUserInfo()
{
}
}
static void Main(string[] args)
{
ObsoleteLib obsoleteLib = new ObsoleteLib();
obsoleteLib.GetUserInfo();
}
- 注意:
- 如果沒有提供錯誤參數,或者如果已經提供了錯誤參數且其值是 false 時,則編譯器將發出警告。
- Obsolete - error 預設值為 false,可加上 message 資訊
public class ObsoleteLib
{
[Obsolete("Stop maintenance in 2017/08/10", false)]
public void GetUserName()
{
}
}
- 若指定錯誤的參數,且該參數擁有 True 值時,編譯器將發出錯誤。
public class ObsoleteLib
{
[Obsolete("Stop maintenance in 2017/08/10", true)]
public void GetUserName()
{
}
}
- 屬性用來描述在屬性類別中被使用的方式
- AttributeTargets validOn:包含 Attribute 列舉型別,需設定給所需要的成員
- Inherited:由衍伸類別繼承並覆寫成員,則為 true;否則為 false
- AllowMultiple:指出是否可以針對單一程式元素指定所指定屬性的多個執行個體
- Code
// AttributeUsage 控制,如何應用新定義的特性
[AttributeUsageAttribute(AttributeTargets.All, // 應用任何元素
Inherited = false, // 不繼承到派生類
AllowMultiple = true)] // 允許應用多次
public class DemoAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Property)]
public class Check : Attribute
{
public int MaxLength { get; set; }
}
public class AttributeLib
{
[Check(MaxLength = 10)]
public string CustomerCode { get; set; }
}
- Main Code:下列有使用 Reflection 讀取 Attribute 的資訊
using System.Reflection;
// 宣告
AttributeLib attributeLib = new AttributeLib();
attributeLib.CustomerCode = "12345678901";
// 取出操作對象的Type (Get the type of the object)
Type objtype = attributeLib.GetType();
// 利用反射取出成員資訊-Reflection 蠻很耗效能 (Loop through all properties)
foreach (PropertyInfo p in objtype.GetProperties())
{
if (p.Name == "CustomerCode")
{
// 取出類別上方的 Attribute
// 取出類別 Class 中隱含的屬性 0~N Attribute (for every property loop through all attributes)
foreach (Attribute a in p.GetCustomAttributes(false)) // Reflection.
{
if (a.GetType().Name == "Check")
{
Check c = (Check)a;
// Do the length check and and raise exception accordingly
if (attributeLib.CustomerCode.Length > c.MaxLength)
{
throw new Exception(" Max length issues ");
}
}
}
}
}
沒有留言:
張貼留言