C# 中的特性

一、概念

  • 特性是一种允许我们向程序的程序集添加元数据的语言结构。它是用于保存程序结构信息的特殊类型的类。(可以通过反射来访问元数据,从而操作特性相关内容)
  • 特性类似于一种声明性标签,可以用于修饰各种元素,包括类,方法,结构体,枚举,属性,变量等。

二、定义

  • 由方括号,特性名和参数列表构成,特性标签会被放在需要被修饰的元素之前。
  • 在一个元素上,可以使用一个或多个特性进行修饰。
  • 特性可以拥有参数。
  • 程序可以使用反射检查自己的元数据或者其他程序中的元数据。

三、示例

  • 单个特性修饰类
[Serializable]	//可序列化
public class MyClass
{
}

自定义特性类时需要主要它的三个参数

  • AttributeTargets 是标注当前特性可用于哪些对象,因为该枚举的值 在二进制中均只有一位为1, 即为2的次方整数值,所以通常通过位运算 或 ( | )来运算。

  • Inherited 表示特性是否可被 修饰类型的派生类继承。

  • AllowMultiple 表示是否可以对同一个目标进行多次修饰。

  • 自定义特性类

	//自定义特性类
    [AttributeUsage(AttributeTargets.All)]  //用于标注当前声明的类应用于哪些对象,All表示全部对象
    public class MyDemoAttribute: Attribute
    {
        public string Description { get; set; }
    }
    
    public class OrderData
    {
        [MyDemo(Description = "订单 ID")]
        public int OrderID { get; set; }

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

        [MyDemo(Description = "计算折扣价")]
        public double Compute(double q)
        {
            return q * 0.8;
        }
    }
  • 向特性类构造函数传递参数
	//向特性类构造函数传递参数
    //特性类只有无参构造,应用时可以忽略小括号。若有有参构造函数,那么应在小括号中添上参数
    [AttributeUsage(AttributeTargets.Class)]
    public class DoubleRangeAttribute: Attribute
    {
        public double Largest { get; }

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

    [DoubleRange(800)]
    public class Test1
    {

    }
  • 同一对象上应用多个特性实例
	//同一对象上应用多个特性实例(AllowMultiple默认为false)
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
    class CustomAttribute: Attribute
    {
        public string Version { get; set; }
    }

    //两种写法
    [Custom(Version = "1.0.0.1"), Custom(Version = "1.0.0.2")]
    [Custom(Version = "1.0.0.3")]
    public class Test2
    {

    }
  • 通过反射进行数据验证处理
    // 声明特性类
    [AttributeUsage(AttributeTargets.Property)]
    public class MyAttribute: Attribute
    {
        public char StartChar {  get; set; }
        public int MaxLen { get; set; }
    }

	//被测试的类
    public class Test3
    {
        [My(StartChar = 'G', MaxLen = 10)]
        public string Name { get; set; }
    }

	internal class Program
    {
        static void Main(string[] args)
        {
            func1();
        }

        static void func1()
        {
        	// 实例化并初始化
            Test3 test3 = new Test3 { Name = "Gzy" };
			// 检查
            bool b = checkTest(test3, nameof(Test3.Name));

            if (b) Console.WriteLine("验证通过");
        }

		/// <summary>
        /// 检查传入的名字在元数据中 是否合法 包括以下3点:
        /// 判断名字是否存在
        /// 判断名字是否以StartChar字段开头
        /// 判断名字长度是否小于MaxLen字段
        /// </summary>
        /// <param name="t">Test3 类型对象</param>
        /// <param name="name">需要判断的字符串</param>
        /// <returns>是否合法</returns>
        static bool checkTest(Test3 t, string name)
        {
            Type type = t.GetType();

            //名字为name的获取属性
            PropertyInfo prop = type.GetProperty(name, 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) //判空
            || value.StartsWith(att.StartChar.ToString()) == false  //判断首字母
            || value.Length > att.MaxLen)   //判断长度
            {
                return false;
            }
            return true;
        }
    }
  • 在返回值上应用特性
    [AttributeUsage(AttributeTargets.ReturnValue)]
    public class CheckSumAttribute: Attribute
    {

    }

    public class Test4
    {
        [return: CheckSum]
        static string Speak() => "HelloWorld";
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KamikazePilot

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值