1. 程式人生 > 其它 >C#Attribute 應用

C#Attribute 應用

特性應用

取得列舉型別的註釋

平時開發時,經常會用到列舉型別及其相關判斷,而有時我們想顯示列舉型別的註釋,怎麼辦?下面用特性來解決這個問題。

namespace AttributeDemo.CustomAttributes
{
    public class RemarkAttribute : Attribute
    {
        private readonly string remark;

        public RemarkAttribute(string remark)
        {
            this.remark = remark;
        }

        
public string GetRemark() { return remark; } } } namespace AttributeDemo.Extensions { public enum UserState { /// <summary> /// 正常 /// </summary> [RemarkAttribute("正常")] Normal = 0, /// <summary> /// 凍結 /// </summary> [RemarkAttribute("
凍結")] Frozen, /// <summary> /// 刪除 /// </summary> [RemarkAttribute("刪除")] Deleted } public static class RemarkExtension { public static string GetRemark(this Enum value) { Type type = value.GetType(); FieldInfo field = type.GetField(value.ToString());
if (field.IsDefined(typeof(RemarkAttribute), true)) { RemarkAttribute attr = field.GetCustomAttribute<RemarkAttribute>(); return attr.GetRemark(); } return value.ToString(); } } }

使用

UserState userState = UserState.Normal;
Console.WriteLine(userState.GetRemark());

資料有效性檢查

一般對於使用者提交的資料,我們都需要進行資料有效性的檢查,之後才能提交到資料庫。本次我們使用特性,優雅的解決這個問題。

宣告檢查資料長度的特性(因為想把資料校驗作為一個共通處理,因此需要首先宣告一個抽象類):

namespace AttributeDemo.CustomAttributes
{

  public abstract class CustomValidateAttribute : Attribute
  {
    public abstract bool Validate(object value);
  }

  public class LengthValidateAttribute : CustomValidateAttribute
  {
    private readonly int minLen;
    private readonly int maxLen;

    public LengthValidateAttribute(int minLen, int maxLen)
    {
      this.minLen = minLen;
      this.maxLen = maxLen;
    }

    public override bool Validate(object value)
    {
      if (value != null && !string.IsNullOrEmpty(value.ToString()))
      {
        int len = value.ToString().Length;
        if (len >= minLen && len <= maxLen)
        {
          return true;
        }
      }
      return false;
    }
  }
}

把特性附加到類中

namespace AttributeDemo
{
  //可以對類整體使用
  [CustomAttribute(description:"類特性示例",remark: "類特性")]
  public class Student
  {
    public int Id { get; set; }
    public string Name { get; set; }
    [LengthValidateAttribute(16, 100)]//追加對郵箱的長度檢查
    public string EMail { get; set; }
    //可以對屬性欄位使用
    [CustomAttribute(description: "屬性示例", remark: "屬性特性")]
    [LengthValidateAttribute(6, 9)]//追加對電話號碼的長度檢查
    public string PhoneNumber { get; set; }
    //可以對方法使用
    [CustomAttribute(description: "方法示例", remark: "方法特性")]
    public void Study()
    {
      Console.WriteLine($"{Name}正在學習中。。。");
    }
    //可以對返回值使用
    [return: CustomAttribute(description: "返回值示例", remark: "返回值特性")]
    public string SayHi([CustomAttribute(description: "引數示例", remark: "引數特性")] string name)//可以對引數列表使用
    {
      return $"Hello {name}";
    }
  }
}

再對Student類新增一個擴充套件方法(如果想對更廣泛範圍的物件進行資料校驗,可以對它們的基類追加擴充套件方法):

public static class ValidateExtension
{
  public static bool Validate(this Student value)
  {
    int errCount = 0;

    Type type = value.GetType();
    PropertyInfo[] properties = type.GetProperties();
    foreach (PropertyInfo property in properties)
    {
      if (property.IsDefined(typeof(CustomValidateAttribute), true))
      {
        IEnumerable<CustomValidateAttribute> attris = property.GetCustomAttributes<CustomValidateAttribute>();
        foreach (CustomValidateAttribute attr in attris)
        {
          if (!attr.Validate(property.GetValue(value)))
          {
            Console.WriteLine($"資料校驗失敗:欄位[{property.Name}]");
            errCount++;
          }
        }
      }
    }

    return errCount == 0 ? true : false;
  }
}

呼叫資料校驗:

Student stu = new Student
{
  Id = 1,
  EMail = "[email protected]",
  Name = "brein",
  PhoneNumber = "1234567890"
};
stu.Validate();

輸出校驗結果:

資料校驗失敗:欄位[PhoneNumber]
資料校驗失敗:欄位[EMail]

以上,是兩個平時用的比較多的關於特性的應用場景。在ASP.NET Core中,特性還有更多應用場景,例如:FilterValidateMVC/API相關特性, AOP應用等等。可以說特性無處不在且非常重要。充分掌握特性相關知識,是掌握ASP.NET Core的充分必要條件。
程式設計是個人愛好