C#中特性的使用

一、简介

记录一下特性的使用方法,特性其实就是一个特殊的类,需要继承Attribute,当我们序列化一个对象时,就需要在其类上标注Serializable,这个就是官方提供的一种特性

二、使用

2.1 定义

[AttributeUsage(AttributeTargets.All)]//约束特性使用范围
public class TestAttribute:Attribute//自定义特性类需要继承于Attribute
{
    
}

2.2 特性类的特点

特性类与普通类相似,可以包含属性,字段,方法等

[AttributeUsage(AttributeTargets.All)]//约束特性使用范围
public class TestAttribute:Attribute//自定义特性类需要继承于Attribute
{
    public int TestProp { get; set; }
    public string TestField;
    
    public void Show()
    {
        Console.WriteLine("特性中的方法");
    }
}     

2.3 使用特性标记

[TestAttribute(TestProp = 11,TestField = "字段")]
public class Test
{
    public string Name { get; set; }
}

2.4 标记好特性之后应该怎么用呢

Test test = new Test();
Type type = test.GetType();
if(type.IsDefined(typeof(TestAttribute), true))//是否被TestAttribute标记,包括它的父类被标记也算
{
    object[] attr = type.GetCustomAttributes(typeof(TestAttribute), true);//获取标记该类型的所有TestAttribute特性
    foreach (TestAttribute attribute in attr )//遍历所有的TestAttribute 特性
    {
          int prop =  attribute.TestProp;
          string fie = attribute.TestField;
          attribute.Show();      
    }
    
}    

2.5 拿到了之后又有什么用呢

 目前我只用到了导出数据到excel时,标注其列名

[AttributeUsage(AttributeTargets.Property)]
public class TitleAttibute : Attribute
{
    public string Title;
}
public class Order
{
  private string _date;
  [TitleAttibute(Title = "订单创建日期")]
  public string Date
  {
    get { return _date; }
    set { _date = value; }
  }
  private string _shift;   [TitleAttibute(Title = "班次")]   public string Shift   {     get { return _shift; }     set { _shift = value;}   } }

导出数据时

Type type = obj.GetType();
List<PropertyInfo> propList = type.GetProperties().
                    Where(c => c.IsDefined(typeof(TitleAttibute), true)).ToList();//找被标记的属性
for (int i = 0; i < propList.Count; i++)//遍历所有被标记的属性,
{
    TitleAttibute properAttribute = propList[i].
                        GetCustomAttribute<TitleAttibute>();
    ICell cell = titleRow.CreateCell(i);
    cell.SetCellValue(properAttribute.Title);//设置列名为标记值
 }

2.6 在学习过程中,看到了其他的用法,比如做数据验证,结合反射,功能更加强大

[AttributeUsage(AttributeTargets.Property)]
public class DeviceAttribute : Attribute
{
  public int DeviceIdLen { get; set; }

  public bool Validate(string deviceid)
  {
    return deviceid!= null && deviceid.Lenght == DeviceIdLen ;
  }
}

该特性用于检测要上传数据库的资产编号长度是否符合要求

public class ModelInfo
{    
  [DeviceAttribute(DeviceIdLen = 22)]
  public string DeviceId{ get; set; }
}
public static class DataCheck
{
  public static bool Validate<T>(this T t) where T : class
  {
    Type type = t.GetType();
    foreach (var prop in type.GetProperties())
    {
      if (prop.IsDefined(typeof(DeviceAttribute ), true)) 
      {
        object obj= prop.GetValue(t);
        foreach (DeviceAttribute attribute in prop.GetCustomAttributes(typeof(DeviceAttribute ), true))
        {
          if(!attribute.Validate(obj))
          {
            return false;
          }
        }
      }
    }
    return true;
  }
}

调用扩展方法验证数据合格性

ModelInfo mo = new();
mo.DeviceId = "20120810153131513";
bool isOk = mo.Validate();
posted @ 2022-08-17 20:21  just--like  阅读(249)  评论(0编辑  收藏  举报