C# 特性

特性


自定义特性类

  特性是一种比较特殊的类,作为代码对象附加部分用于向运行时提供一些补充信息。

  主要有三个特征:

  • 从Attribute类派生
  • 名称一般以Attribute结尾
  • 声明特性类时必须在类上加AttributeUsage,用于标注当前声明的类应用于哪些对象
    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)]
    public class MyDemoAttribute : Attribute
    {
        public string Description { get; set; }
    }

    public class OrderData
    {
        [MyDemo(Description = "订单 ID")]
        public int OrdID { get; set; }

        [MyDemo(Description = "添加时间")]
        public DateTime AddTime { get; set; }

        [MyDemo(Description = "计算折扣价")]
        public double Compute(double q)
        {
            return q * 0.98d;
        }
    }

向特性类构造函数传递参数

  特性类若只有无参构造函数,应用时可以忽略小括号。若有有参构造函数,那么应在小括号中填上参数。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
    public class DoubleRangeAttribute : Attribute
    {
        public double Largest { get; }

        public DoubleRangeAttribute(double largest)
        {
            Largest = largest;
        }
    }

    [DoubleRange(700d)]
    public class Test
    {

    }

同一对象上应用多个特性

  声明特性类时,AttributeUsage类的AllowMultiple属性用于设置是否允许在同一对象上应用多个特性实例,默认false

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
    public class CustomAttribute : Attribute
    {
        public string Ver { get; set; }
    }

    [Custom(Ver = "1.0.0.1"), Custom(Ver = "1.0.2.0")]
    public class AppData
    {

    }

运行阶段对数据验证

  声明一个特性类

    [AttributeUsage(AttributeTargets.Property)]
    public class MyAttribute : Attribute
    {
        public char StartChar { get; set; }
        public int MaxLen { get; set; }
    }

  把MyAttribute特性应用到测试类的RawName属性上,StartChar表示以“k”开头,MaxLen表示最大长度为7.

    public class Test
    {
        [My(StartChar = 'k', MaxLen = 7)]
        public string RawName { get; set; }
    }

  需要用到反射,通过Type类得到对象的各种信息,通过GetCustomAttribute扩展方法得到已应用的特性实例。

    class Program
    {
        static void Main(string[] args)
        {
            Test v = new Test { RawName = "k003d6ex915f" };
            // 调用方法进行属性值验证
            bool b = CheckTest(v, nameof(Test.RawName));
            if (b)
                Console.WriteLine("验证通过。");
            else
                Console.WriteLine("验证失败。");

            Console.Read();
        }

        static bool CheckTest(Test t, string property)
        {
            // 获取类型信息
            Type type = t.GetType();
            // 查找属性成员
            PropertyInfo prop = type.GetProperty(property, BindingFlags.Public | BindingFlags.Instance);
            if (prop == null)
            {
                return false;
            }
            // 获取特性
            MyAttribute att = prop.GetCustomAttribute<MyAttribute>();
            // 获取实例的属性值
            string value = prop.GetValue(t) as string;
            if (string.IsNullOrEmpty(value))
                return false;
            // 进行验证
            if (value.StartsWith(att.StartChar) == false)
                return false;
            if (value.Length > att.MaxLen)
                return false;

            return true;
        }
    }

返回值上应用特性

    [AttributeUsage(AttributeTargets.ReturnValue)]
    public class CheckSumAttribute : Attribute
    {

    }
    [return: CheckSum]
    static string SaySomething() => "Hello";

posted @ 2021-09-29 09:43  一纸年华  阅读(1679)  评论(0编辑  收藏  举报