首页 > 编程语言 >学习笔记:C#高级进阶语法——特性(Attribute)

学习笔记:C#高级进阶语法——特性(Attribute)

时间:2025-01-03 10:30:04浏览次数:1  
标签:进阶 标记 C# Attribute 特性 CustomAttribute true public string

三、特性(Attribute)

3.1、特性的本质

什么是特性?

特性本质是一个类,直接或间接的继承自抽象类Attribute,可以把这个类,用[类名]进行注册标记到类似及类内部的所有成员:约定俗成,默认以Attribute结尾,在进行标记的时候,如果特性类是Attribute结尾的,可以省略不写结尾的Attribute。

特性的约束?

[AttributeUsage(AttributeTargets.All,AllowMultiple = true,Inherited = true)],用来约束特性的特性,AttributeTargets约束用途,AllowMultiple 为true的时候,表示这个特性可以在一个类或者属性等上重复标记,Inherited = true表示这个特性可以被继承。

3.2、特性和注释的区别

注释在编译器编译后是不存在的

3.3、特性的调用

{
    //标记好的特性要如何调用?
    //要调用特性,必须用到反射
    //1、使用反射
    //两种方式都可以
    Type type = student.GetType();
    //Type type = typeof(Student);
    //2、获取特性实例,标准用法---先判断,再获取实例
    if (type.IsDefined(typeof(CustomAttribute), true)) {
        CustomAttribute customAttribute = type.GetCustomAttribute<CustomAttribute>();//执行特性的构造函数 
    }
    //获取属性上的特性
    foreach (var prop in type.GetProperties())
    {
        if (prop.IsDefined(typeof(CustomAttribute), true))
        {
            CustomAttribute attribute = prop.GetCustomAttribute<CustomAttribute>();
        }
    }
    //获取字段上的特性
    foreach (var field in type.GetFields())
    {
        if (field.IsDefined(typeof(CustomAttribute), true))
        {
            CustomAttribute attribute = field.GetCustomAttribute<CustomAttribute>();
        }
    }
    //获取方法上的特性
    foreach (var mehtod in type.GetMethods())
    {
        if (mehtod.IsDefined(typeof(CustomAttribute), true))
        {
            CustomAttribute attribute = mehtod.GetCustomAttribute<CustomAttribute>();
        }
    }
    //特性是一个类,获取到一个实例,--就是得到了一个类的实例
}

定义特性

namespace C_MyAttribute
{

    [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
    public class CustomAttribute : Attribute
    {
        private int _Id { get; set; }
        public string _Name { get; set; }

        public int _Age;

        public CustomAttribute()
        {

        }

        public CustomAttribute(int id)
        {
            this._Id = id;
        }

        public CustomAttribute(string name)
        {
            this._Name = name;
        }

        public void Do()
        {
            Console.WriteLine("this is  CustomAttribute");
        }
    }


    public class ChildStudent : CustomAttribute
    {

    }
}


标记特性

namespace C_MyAttribute
{
    /// <summary>
    /// 这是一个Student类
    /// </summary>
    // [Obsolete("请不要使用这个了,请使用什么来代替",true)]//系统 --在之前--标记的这玩意还可以影响编译器
    //; [Serializable]//可以序列化和反序列化  --类标记了这个特性以后,就可以做序列化 
    [Custom(id: 234)] //不允许标记两个 对应的无参数构造函数
    [Custom]  //标记到类

    public class Student
    {
        /// <summary>
        /// 
        /// </summary>
        [Custom(1234)]  //标记到属性
        public int Id { get; set; }
        public string Name { get; set; }

        [CustomAttribute("Richard")]  //标记到字段
        public string Description;

        [CustomAttribute(_Age = 30)]  //标记到方法
        public void Study()
        {
            Console.WriteLine($"这里是{this.Name}跟着Eleven老师学习");
        }

        /// <summary>
        /// 提问
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns> 
        [return: CustomAttribute]  //标记到方法的返回值
        public string Answer([CustomAttribute] string name)  // [CustomAttribute]  //标记到方法的参数
        {
            return $"This is {name}";
        }

        [CustomAttribute]  //标记到委托
        public delegate void StudentDelegate();

        //索引器 
        [CustomAttribute]  //标记到索引器
        public Index[] values;
    }
}

3.4、特性的价值

特性到底可以带来什么?
1.特性可以提供额外信息----本来不具备这个信息的,可以通过特性来增加
2.特性可以提供额外功能----本来不具备这个功能的,可以通过特性来支持这个功能

实例:我定义了一个枚举用来表示用户状态,但是他们的中文含义无法定义,需要在使用的时候,用if去判断输出

namespace C_MyAttribute
{
    public enum UserStateEnum
    {
        /// <summary>
        /// 正常
        /// </summary>
        Normal = 0,

        /// <summary>
        /// 已冻结
        /// </summary>
        Frozen = 1,

        /// <summary>
        /// 已删除
        /// </summary>
        Deleted = 2
    }
}
UserInfo userInfo = new UserInfo()
{
    Id = 1,
    Name = "Seven",
    Age = 20,
    Mobile = "18888888888",
    State = UserStateEnum.Normal
};
{
    //原始做法,根据枚举来判断,得到中文状态
    if (userInfo.State == UserStateEnum.Normal)
    {
        Console.WriteLine("用户状态为正常");
    }
    else if (userInfo.State == UserStateEnum.Frozen)
    {
        Console.WriteLine("用户状态为已冻结");
    }
    else if (userInfo.State == UserStateEnum.Deleted)
    {
        Console.WriteLine("已删除");
    }
    //多个页面要使用,则都要做判断
}

如何利用特性来扩展他,让我在得到状态的时候,就可以知道它的中文注释

1、定义特性

namespace C_MyAttribute.Extend
{
    /// <summary>
    /// 状态描述
    /// </summary>
    [AttributeUsage(AttributeTargets.Field)]
    public class RemarkAttribute : Attribute
    {
        private string _Desctiption;
        public RemarkAttribute(string desctiption)
        {
            _Desctiption = desctiption;
        }

        public string GetDescription() => _Desctiption;
    }
}

2、在枚举上面标记特性

using C_MyAttribute.Extend;

namespace C_MyAttribute
{
    public enum UserStateEnum
    {
        /// <summary>
        /// 正常
        /// </summary>
        [Remark("正常")]
        Normal = 0,

        /// <summary>
        /// 已冻结
        /// </summary>
        [Remark("已冻结")]
        Frozen = 1,

        /// <summary>
        /// 已删除
        /// </summary>
        [Remark("已删除")]
        Deleted = 2
    }
}

3、封装调用

using C_MyAttribute.Extend;
using System.Reflection;

namespace C_MyAttribute
{
    public class DescriptionManager
    {
        public static string GetDescription(object oValue)
        {
            Type type = typeof(UserStateEnum);
            FieldInfo field = type.GetField(oValue.ToString());
            if (field.IsDefined(typeof(RemarkAttribute), true))
            {
                RemarkAttribute attribute = field.GetCustomAttribute<RemarkAttribute>();
                string description = attribute.GetDescription();
                Console.WriteLine(description);
                return description;
            }
            else
            {
                return oValue.ToString();
            }
        }
    }
}
//使用
Console.WriteLine(DescriptionManager.GetDescription(userInfo.State));

对特性的方式进行升级优化

将封装的调用定义为扩展方法,并且限定传入的参数为枚举类型

using C_MyAttribute.Extend;
using System.Reflection;

namespace C_MyAttribute
{
    public static class DescriptionManager
    {
        /// <summary>
        /// 静态类中的静态方法,同时第一个参数用this修饰,叫扩展方法
        /// </summary>
        /// <param name="oValue"></param>
        /// <returns></returns>
        public static string GetDescription(this Enum oValue)
        {
            FieldInfo field = oValue.GetType().GetField(oValue.ToString());
            if (field.IsDefined(typeof(RemarkAttribute), true))
            {
                RemarkAttribute attribute = field.GetCustomAttribute<RemarkAttribute>();
                string description = attribute.GetDescription();
                Console.WriteLine(description);
                return description;
            }
            else
            {
                return oValue.ToString();
            }
        }
    }
}

对实体中增加一个属性,直接获取枚举对应的中文注释

namespace C_MyAttribute
{
    public class UserInfo
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public int Age { get; set; }

        public long QQ { get; set; }
        public string Mobile { get; set; }

        /// <summary>
        /// 用户的状态
        /// </summary>
        public UserStateEnum State { get; set; }


        public string StrDescription
        {
            get
            {
                return this.State.GetDescription();
            }
        }
    }
}

{
    UserInfo userInfo1 = new UserInfo() {
        Id = 1,
        Name = "Seven",
        Age = 20,
        Mobile = "18888888888",
        State = UserStateEnum.Normal                     
    };

    Console.WriteLine(userInfo1.StrDescription);
}

标签:进阶,标记,C#,Attribute,特性,CustomAttribute,true,public,string
From: https://www.cnblogs.com/SevenDouble/p/18649545

相关文章

  • 解决微信二维码接口接口返回:errcode\":47001,\"errmsg\":\"data format error rid
    dataformaterrorrid问题:在php中使用curl调用微信二维码生成接口getwxacodeunlimit时得到错误响应信息:errcode\":47001,\"errmsg\":\"dataformaterrorrid:xxx在微信开发者社区看了几个帖子全是在胡说,还有width参数不能小于280这种,真是笑死。。。解决:最终确定原因是接......
  • 开源零代码平台 敲敲云, Docker 一键安装启动
    Docker快速启动第一步:下载项目gitclonehttps://gitee.com/jeecg/qiaoqiaoyun.git第二步:手工解压出dist和qiaoqiaoyun-start-2.0.jar进入qiaoqiaoyun/安装源目录,手工解压准备后续使用。进入qiaoqiaoyun/安装源目录,手工解压准备后续使用。第三步:在安装源目录......
  • 你有使用过backdrop-filter吗?它有什么作用?
    在前端开发中,我确实使用过backdrop-filter这一CSS属性。backdrop-filter是一个功能强大的属性,它允许开发者为元素背后的区域添加图形效果,如模糊、颜色偏移等,从而创造出新颖、引人注目的界面设计。作用具体来说,backdrop-filter可以应用于元素的背景,通过应用不同的滤镜函数,改变元......
  • What is the naming convention for Landsat Collections Level-1 scenes?
    WhatisthenamingconventionforLandsatCollectionsLevel-1scenes?Link:https://www.usgs.gov/faqs/what-naming-convention-landsat-collections-level-1-scenesThe LandsatCollection1 Level-1productidentifierincludestheCollectionprocessinglevels,......
  • 【前端】react入门级写法介绍和部分Demo
    React是一个由Facebook维护的用于构建用户界面的JavaScript库,特别是单页应用中数据渲染部分。它允许开发者创建复杂的UI界面,并且高效地更新和渲染当数据变化时的视图。React的核心理念是组件化开发,即通过组合小的、可重用的代码片段(组件)来构建整个应用程序。以下是十个常见......
  • 请说说CommonJS的规范有哪些?
    CommonJS(简称CMJ)是一种服务端模块化规范,以下是关于CommonJS规范的具体内容:一、模块定义文件即模块:在CommonJS规范中,每个文件都被视为一个独立的模块,模块内部定义的变量、函数、类等默认是私有的,对其他模块不可见。模块作用域:模块内部的所有代码都运行在模块作用域内,不会污染全......
  • wx.canvasToTempFilePath
    wx.canvasToTempFilePath(Objectobject,Objectthis)以Promise风格调用:支持小程序插件:支持,需要小程序基础库版本不低于1.9.6微信Windows版:支持微信Mac版:支持相关文档:画布指南、canvas组件介绍功能描述把当前画布指定区域的内容导出生成指定大小的图片。在......
  • opencv computeCorrespondEpilines函数
    cv::computeCorrespondEpilines函数在OpenCV中用于计算对应点的极线。这在立体视觉中非常重要,因为它可以帮助我们确定一对立体图像中对应点的匹配关系。函数原型voidcv::computeCorrespondEpilines(InputArraypoints,intmode,InputArrayF,OutputArra......
  • wx.createCanvasContext
    CanvasContextwx.createCanvasContext(stringcanvasId,Objectthis)从基础库2.9.0开始,本接口停止维护,请使用Canvas代替小程序插件:支持,需要小程序基础库版本不低于1.9.6微信Windows版:支持微信Mac版:支持微信鸿蒙OS版:支持相关文档:旧版画布迁移指南、canvas......
  • wx.canvasPutImageData
    wx.canvasPutImageData(Objectobject,Objectthis)基础库1.9.0开始支持,低版本需做兼容处理。以Promise风格调用:支持小程序插件:支持,需要小程序基础库版本不低于1.9.6微信鸿蒙OS版:支持相关文档:画布指南、canvas组件介绍功能描述将像素数据绘制到画布。在......