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 = "xxxxx@xxxx.com",
  Name = "brein",
  PhoneNumber = "1234567890"
};
stu.Validate();

输出校验结果:

数据校验失败:字段[PhoneNumber]
数据校验失败:字段[EMail]

以上,是两个平时用的比较多的关于特性的应用场景。在ASP.NET Core中,特性还有更多应用场景,例如:FilterValidateMVC/API相关特性, AOP应用等等。可以说特性无处不在且非常重要。充分掌握特性相关知识,是掌握ASP.NET Core的充分必要条件。
上一篇:pyqt5 'QWidget' object has no attribute 'setCentralWidget'


下一篇:Pyinstaller:AttributeError: module ‘enum‘ has no attribute ‘IntFlag‘ 问题解决