在通過Visual Studio創建的C 程式集中,都包含了一個AssemblyInfo.cs的文件,在這個文件中,我們常常會看到這樣的代碼 從這些代碼及他們的註釋中,我們大概知道他們是用來描述程式集的相關信息,那麼是不是我們平常寫的代碼中的類、類成員是不是也有這樣的附加信息呢?答案是肯定的。比如最 ...
在通過Visual Studio創建的C#程式集中,都包含了一個AssemblyInfo.cs的文件,在這個文件中,我們常常會看到這樣的代碼
[assembly: AssemblyTitle("AttributeTutorial")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AttributeTutorial")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
從這些代碼及他們的註釋中,我們大概知道他們是用來描述程式集的相關信息,那麼是不是我們平常寫的代碼中的類、類成員是不是也有這樣的附加信息呢?答案是肯定的。比如最常見的位枚舉、調用另一種語言開發的dll...
[Flags]
enum Actions
{
None = 0,
Read = 0x01,
Write = 0x02,
ReadWrite = Read | Write,
Delete = 0x04
}
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
定製自己的Attribute
定製自己的Attribute
類,首先要繼承System.Attribute
,並用Attribute
作為尾碼。下麵的例子中的DescriptionAttribute
其實在System.ComponentModel
下已近有實現,這裡我們只是作為一個自己的簡單的例子
//AttributeUsage的第一個參數,告訴編譯器這個特性應用的範圍,第二個參數指的是派生類及重寫成員是否也繼承該特性,第三個參數表示是否可以為類型或成員指定多個特性
[System.AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
sealed class DescriptionAttribute : Attribute
{
// See the attribute guidelines at
// http://go.microsoft.com/fwlink/?LinkId=85236
readonly string description;
// This is a positional argument
public DescriptionAttribute(string description)
{
this.description = description;
// TODO: Implement code here
}
public string Description
{
get { return description; }
}
// This is a named argument
public int NamedInt { get; set; }
}
下麵我們就用剛纔自定義的特性,來簡單的完成一些事情,首先我們像下麵那樣把剛纔的枚舉類型加上我們定義的特性
[Flags]
[Description("文件的訪問")]
enum Actions
{
None = 0,
Read = 0x01,
Write = 0x02,
ReadWrite = Read | Write,
Delete = 0x04
}
那麼加上這個特性有什麼用呢?怎麼體現他的作用呢?不要著急,我們這就來實現
[Description("主程式")]
class Program
{
static void Main(string[] args)
{
ClassDescriptionDisplay(typeof(Actions));
ClassDescriptionDisplay(typeof(Program));
Console.ReadKey();
}
static void ClassDescriptionDisplay(Type type)
{
if (type.IsDefined(typeof(DescriptionAttribute), false))//檢測類型是否包含此特性
{
DescriptionAttribute attrs = (DescriptionAttribute)type.GetCustomAttributes(typeof(DescriptionAttribute), false)[0];//獲取特性
Console.WriteLine("{0}:{1}",type.Name,attrs.Description);
}
else
{
//另外的處理
}
}
}
通過上面的代碼,現在我們知道,我們可以為類及他的成員添加好配置,然後在程式運行的過程中根據配置動態的去處理一些問題。其實這個也就是特性的最大功能。
應用
特性的應用範圍很廣,比如我們可以為實體類的各個屬性添加一個特性,這樣的話在保存數據的時候不用再一個個的去寫屬性的判斷,比如序列化的時候,只想序列化部分欄位,但是要完成這些功能,還需要進一步學習反射的相關知識,這一篇我們的重點是在定製特性
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "電子郵件")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "{0} 必須至少包含 {2} 個字元。", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "密碼")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "確認密碼")]
[Compare("Password", ErrorMessage = "密碼和確認密碼不匹配。")]
public string ConfirmPassword { get; set; }
}