Attribute特性定义及应用

C# 特性(Attribute)总结 特性的作用就是对程序中所标记元素的另加描述和限限制。就像生活中的坐火车的车票一样,对该行程进行了进一步描述(如哪个站,目的地,出发时间等),同时也对描述信息进行了限制(如你错过发车时间就不能上车),出现任何差错都会视为异常。 阅读详情

目录

一、前期准备

二、特性概念

三、特性案例

1、基础特性 -- 自定义

2、特性实战 -- 自定义

3、常用特性类 -- 官方

1、ObsoleteAttribute

2、AttributeUsageAttribute

3、ConditionalAttribute

4、CallerFilePath、CallerLineNumber、CallerMemberName

5、DebuggerStopThrough

6、RequiredAttribute


涉及知识点:   特性    反射

一、前期准备

 引入using:

using System;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;

二、特性概念

特性: 他就是一个类, 继承Attribute,在特性类中,一般只配置 字段、属性、构造方法
使用场景:数据验证
特性三大步:
         第一步 -- 定义特性  (编写一个类)
                               类需要继承Attribute,
                               并以Attribute为后缀
         第二步 -- 标记 -- 标记时可省略Attribute后缀
         第三步 -- 反射调用

三、特性案例

1、基础特性 -- 自定义

代码编写:

    class NameAttribute : Attribute  //第一步创建以Attribute结尾的类,并继承Attribute类
    {
        public string name; //字段
        public int Id { set; get; } //属性
        public NameAttribute(string name) //构造方法
        {
            this.name = name;
        }
        public NameAttribute(string name, int id) //构造方法
        {
            this.name = name;
            this.Id = id;
        }
    }

    class Student
    {
        [Name("小王", 1)] //第二步 标记特性,可省略Attribute后缀
        public int Id { get; set; }
        [Name("小白")]
        public string Name { get; set; }
    }
    
    class AttributeInvoke
    {
        public static void Invoke<T>(T t) //第三步编写反射调用特性使用方法
        {
            //获取类
            Type type = typeof(T);
            //遍历类中的属性
            foreach (PropertyInfo property in type.GetProperties())
            {
                //若该属性有NameAttribute标记
                if (property.IsDefined(typeof(NameAttribute), true))
                { 
                    //获取NameAttribute特性
                    NameAttribute name = property.GetCustomAttribute<NameAttribute>();
                    Console.WriteLine(name.name);
                    Console.WriteLine(name.Id);
                }
            }
        }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            Student student = new Student();
            AttributeInvoke.Invoke(student);
            Console.WriteLine("Hello World!");
        }
    }

结果显示:

2、特性实战 -- 自定义

第一步:创建抽象公共特性类
第二步:编写多个正常特性类,继承公共特性类
第三步:编写反射调用特性方法
第四步:标记,并调用特性方法,校验

代码编写:

    //第一步: 创建抽象公共特性类
    public abstract class CommonValidateAttribute : Attribute
    {
        public abstract bool Validate(object obj);
    }

    //第二步: 编写多个正常特性类,继承公共特性类
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
    public class LengthAttribute : CommonValidateAttribute
    {
        public int Max;
        public int Min;
        public LengthAttribute(int max, int min)
        {
            Max = max;
            Min = min;
        }

        public override bool Validate(object objValue)
        {
            return objValue != null &&
                   objValue.ToString().Length < Max &&
                   objValue.ToString().Length > Min;
        }
    }
    public class NameLengthAttribute : CommonValidateAttribute
    {
        public int count;
        public NameLengthAttribute(int count)
        {
            this.count = count;
        }

        public override bool Validate(object objValue)
        {
            return objValue.ToString().Length == count;
        }
    }

    //第三步:编写反射调用特性方法
    public class AttributeInvoke
    {
        public static bool Invoke<T>(T t)
        {
            Type type = typeof(T);
            foreach (FieldInfo field in type.GetFields())
            {
                Object objValue = field.GetValue(t);
                foreach (CommonValidateAttribute item in field.GetCustomAttributes(typeof(CommonValidateAttribute), true))
                {
                    return item.Validate(objValue);
                }
            }
            return false;
        }
    }
    //第四步:标记,并调用特性方法,校验
    public class Student
    {
        [NameLength(3)]
        public string name;
        [Length(15, 8)]
        public long Phone;
    }
    internal class Program
    {
        static void Main(string[] args)
        {
            string information;
            Student Tom = new Student()
            {
                name = "王小红",
                Phone = 123456789
            };
            information = AttributeInvoke.Invoke(Tom) ?  "数据正确" : "数据格式错误";
            Console.WriteLine(information);

            Student Jack = new Student()
            {
                name = "小白",
                Phone = 123
            };
            information = AttributeInvoke.Invoke(Jack) ? "数据正确" : "数据格式错误";
            Console.WriteLine(information);
        }
    }

结果显示:

3、常用特性类 -- 官方

1、ObsoleteAttribute

概念:

       [Obsolete] -- 类已过时
                       -- 系统自动调用
                       -- 默认警告提示

代码编写:

    internal class Program
    {
        static void Main(string[] args)
        {
            Student Tom = new Student()
            {
                id = 2,       //绿色波浪线
                name = "Tom", //绿色波浪线
                phone = 15258545856, //红色波浪线
                email = "2578395032@qq.com", //绿色波浪线
            };
            Console.WriteLine("Hello World!");
        }
    }
    public class Student
    {
        [Obsolete]  // 已过时(抛警告)
        public int id;

        [Obsolete("2022.12.10废弃")] //默认是false -- 推荐
        public string name;

        [Obsolete("不可用", true)]  //调用时报红色波浪线错误 -- 编译不可以通过,错误
        public long phone;

        [Obsolete("已废弃", false)] //调用时报绿色波浪线警告 -- 编译可以通过,警告
        public string email;
    }

结果显示:

2、AttributeUsageAttribute

概念:

        [AttributeUsage] -- 配置特性标记范围

代码编写:

    //设置Student特性只能应用于类和方法上,默认 不允许多个特性,可查询特性的父类
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class TeacherAttribute : Attribute
    {
        public TeacherAttribute() { }
    }

    [Teacher]
    [Teacher]  //报红,报错,不可标记多个特性
    public class Student
    {
        [Teacher]  //报红,报错,只能标记在类和方法上面
        public string Name { get; set; }
    }

3、ConditionalAttribute

概念:

        [Conditional]   -- 条件编译 -- 只可应用在方法和特性类上
                             -- 若定义,正常调用
                             -- 若未定义,则不被调用

代码编写:

    #define teacherAttribute
    //#define fun
    
    [Conditional("teacherAttribute")]
    public class TeacherAttribute : Attribute
    {
        public string name;
        public TeacherAttribute(string name)
        {
            this.name = name;
        }
    }

    [Teacher("学生")]
    public class Student
    {
        [Conditional("teacherAttribute")]
        public void Music() => Console.WriteLine("听音乐");
        [Conditional("fun")]
        public void Song() => Console.WriteLine("唱歌");
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            Student student = new Student();
            student.Music(); //fun 定义 -- 运行
            student.Song(); //teacherAttribute 未定义 -- 不运行

            //校验Teacher特性 -- fun 定义,运行
            Type type = typeof(Student);
            if (type.IsDefined(typeof(TeacherAttribute), true))
            {
                TeacherAttribute attribute = (TeacherAttribute)type.GetCustomAttribute(typeof(TeacherAttribute), true);
                Console.WriteLine(attribute.name);
            }

            Console.WriteLine("Hello World!");
        }
    }

结果显示:

4、CallerFilePath、CallerLineNumber、CallerMemberName

概念:

        只可用于方法的入参
        [CallerFilePath] --文件路径
        [CallerLineNumber] -- 代码行数
        [CallerMemberName] -- 成员名称

代码编写:

    //只可应用于参数
    internal class Program
    {
        static void Main(string[] args)
        {
            Student student = new Student();
            student.Music();
            Console.WriteLine("Hello World!");
        }
    }
    class Student
    {
        public void Music([CallerMemberName] string memberName = "",
                          [CallerFilePath] string filePath = "",
                          [CallerLineNumber] int lineNumber = 0)
        {
            Console.WriteLine("听音乐");
            Console.WriteLine("memberName: " + memberName);
            Console.WriteLine("filePath:   " + filePath);
            Console.WriteLine("lineNumber  " + lineNumber);
        }
    }

结果显示:

5、DebuggerStopThrough

概念:

        [DebuggerStopThrough] -- 调试时不进入此方法,方法内部正常调用

代码编写:

    internal class Program
    {
        static void Main(string[] args)
        {
            Student student = new Student();

            student.Music();
            Console.WriteLine("Hello World!");
        }
    }
    class Student
    {
        [DebuggerStepThrough] //调试时不进入此方法,方法内部正常调用
        public void Music()
        {
            Console.WriteLine("听音乐");
        }
    }

6、RequiredAttribute

概念:

        [Required] -- 属性不能为 ""
                        -- 一般应用于string类型上面,不建议放在int类型上面

代码编写:

    internal class Program
    {
        static void Main(string[] args)
        {
            Student student = new Student();
            Type type = typeof(Student);
            foreach (PropertyInfo property in type.GetProperties())
            {
                object objValue = property.GetValue(student);
                if (property.IsDefined(typeof(RequiredAttribute), true))
                {
                    RequiredAttribute required = (RequiredAttribute)property.GetCustomAttribute(typeof(RequiredAttribute), true);
                    if (!required.IsValid(objValue))
                    {
                        Console.WriteLine($"{property.Name} 验证不通过");
                    }
                }
            }

            Console.WriteLine("--" +student.Name);
            Console.WriteLine("--" +student.Id);
            Console.WriteLine("Hello World!");
        }
    }
    class Student
    {
        [Required] //int一般不用这个特性
        public int Id { get; set; }

        [Required] //一般应用于string类型
        public string Name { get; set; }
    }

结果显示:

如有错误,烦请批评指正

Unity项目开发框架总结一 1、值类型:值类型是在栈中分配内存,在声明时初始化才能使用,不能为null。值类型超出作用范围系统自动释放内存主要由两类组成:结构、枚举(enum),结构分为以下几类①整形(Sbyte、Byte、Char、Short、Ushort、Int、Uint、Long、Ulong)②浮点型(Float、Double)③decimal④bool⑤用户自定义的结构(struct)2、引用类型引用类型在堆中分配内存,初始化时默认为null。引用类型是通过垃圾回收机制进行回收。包括类、接口、委托、 阅读详情

相关推荐

深入浅出话窗体(一)——窗体事件模型(上)

 深入浅出话窗体(一)——窗体事件模型(上) 作者:优快云 刘铁猛    小序:            工作中最大的挑战并不是那些Mission Impossible,而是你需要一边保持安静、平衡的心态以专注于工作,一边对抗公司体制、社会经济和人际环境对这种心态的破坏——这是对儿永远也解不开的矛盾。         正文:            记得我在前

水之真谛 5863

C#的自定义属性AttributeUsage用法

// 描述如何使用一个自定义特性 SomethingAttribute [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)] //********自定义特性SomethingAttribute**************// public cl...

星河队长 2161

C#- Attribute(特性)

C# 的Attribute(特性)用法预定义的特性可以用来为代码添加元数据和指示编译器和运行时执行特定的操作。同时可以增加代码的功能和可读性。[Serializable] 特性:用于标记一个类或结构体可序列化,并可以在网络上传输或保存到磁盘上。// ...[Obsolete] 特性:用于标记一个方法、属性或类已经过时,并提供相应的替代方案或建议。下面设置为true是启动报错。默认为false。// ...[Conditional] 特性:用于指定一个方法只有在满足特定条件编译指令时才会被编译。

Bruce__taotao的博客 1689

C#特性(Attribute)

Obsolete。.Net Framework 允许您创建自定义特性,自定义特性不仅可以用于存储声明性的信息,还可以在运行时被检索。声明自定义特性;构建自定义特性;在目标程序上应用自定义特性;通过反射访问特性。最后一步涉及编写一个简单的程序来读取元数据以便查找各种符号。元数据是有关数据或用于描述其他数据信息的数据。该程序应在运行时使用反射来访问属性。// 一个自定义特性 DeBugInfo 被赋给类及其成员。

uaenana的博客 1061

高通thermal-engine.conf配置详解:从虚拟传感器到CPU频率控制的完整指南

本文深入解析了高通thermal-engine.conf配置文件的架构与调优方法。从虚拟传感器的加权融合原理,到监控算法与CPU频率控制的多级策略,提供了完整的配置详解与实战调试指南。文章旨在帮助开发者与高级用户掌握底层温控逻辑,在性能与散热间实现精准平衡,并详细介绍了日志调试与场景化配置等高级技巧。

weixin_28327051的博客 494

BetaFlight开源飞控源码分析

BetaFlight是穿越机领域比较成熟的开源飞控,本篇文章主要分析一下源代码以及如何使用这个开源代码

weixin_43811044的博客 1万+

C# 特性(Attribute)详解:预定义与自定义特性应用教程

C#特性(Attribute)是为程序元素添加元数据的声明性标签,可分为预定义特性和自定义特性。预定义特性包括AttributeUsage(控制特性使用范围)、Conditional(条件编译)和Obsolete(标记过时代码)。自定义特性通过继承System.Attribute类实现,可定义必需参数和可选属性,并通过反射在运行时读取。特性广泛应用于代码控制、编译优化和元数据存储,是C#高级编程的重要工具。

bugcome的博客 451

MicroPython学习:在STM32上进行移植

本文将介绍如何在STM32上移植MicroPython,并提供相应的源代码。通过以上步骤,你已经成功地将MicroPython移植到STM32上,并可以使用MicroPython语言编写和运行代码。你可以进一步探索MicroPython的功能和API,以利用STM32的各种外设和功能。使用STM32CubeProgrammer或其他适当的烧录工具,将编译生成的MicroPython固件烧录到STM32微控制器中。打开该文件,并根据你的STM32微控制器类型进行必要的配置更改。模块来控制STM32的LED。

JeeVue的博客 1237

总结一下 C# 如何自定义特性 Attribute 并进行应用

Attribute(特性)是一种用于为程序元素(如类、方法、属性等)提供元数据信息的方法,描述其用途、状态、约束等,可以在运行时通过反射获取并读取,用于实现一些动态的行为,如配置加载、权限检查等,应用范围非常广泛,在实际开发中经常用于标记和控制程序的行为,提高代码的可读性和灵活性

yangshuquan的专栏 2091

利用插件扩展 Qt 应用程序

不仅 Qt 本身可以通过插件进行扩展,而且 Qt 应用程序也可以通过插件来扩展,这需要应用程序使用 `QPluginLoader` 检测和加载插件。

青春不老,奋斗不止! 1万+

银河麒麟桌面系统 必会操作 | 加装双系统(麒麟桌面系统+Windows系统)的详细方法(含常见故障和解决方法)

装好麒麟桌面操作系统的电脑上、再加装Windows 操作系统的详细方法;和在已经装好Windows系统的电脑上、再加装麒麟桌面操作系统的详细方法;含加装双系统过程中常见问题的解决方法。

qq_33216613的博客 2416

DotNetGuide特性编程:自定义Attribute的应用

在.NET开发中,我们经常需要为代码元素(类、方法、属性等)添加额外元数据,用于描述其行为、用途或约束。传统方式往往依赖注释或配置文件,不仅维护成本高,还无法在运行时动态获取。自定义Attribute(特性)正是解决这一痛点的强大工具——它允许开发者将元数据直接嵌入代码,通过反射机制在编译时或运行时灵活读取,实现业务逻辑与元数据的解耦。 **读完本文你将掌握:** - Attribute的核心工...

gitblog_00871的博客 994

杰理-tone

低音质格式切换高音质格式:切换提示音格式,未导出,编译下载没有提示音;提示音导出,再次编译下载,提示音正常高音质格式切换低音质格式:不需要导出,直接编译下载,提示音正常。

m0_67447112的博客 955

C#特性Attribute应用

输出:

mengningyun6826的博客 462

uniapp 全局弹窗

功能详解1.有的组件需要全局调用,不想要在一个页面里面一个个引入,现在就需要写入到全局中,直接全局触发。2.通过 $rechargePop就能全局触发 充值的弹窗实现步骤一、先把组件封装好,如 rechargePop组件位置 components/RechargePop/index.vue ,就定义一个methods open方法就可以 二、在同级别路径下定义一个 index.js 三、引入到main.js 四、全局调用this.$rechargePop(); 就能弹出那个弹窗

weixin_42066070的博客 657

Android11车机系统海外项目资源包RRO方案优化

本文介绍了汽车设置应用如何通过Android RRO(运行时资源叠加)方案实现多车型差异化资源管理。针对不同车型(国内/海外、轿车/SUV)和配置(方向盘、轮毂等),采用产品变体(productFlavors)构建不同APK版本,并通过JSON配置文件动态启用对应资源包。系统根据车辆下线配置自动匹配适用的资源叠加包,解决了硬编码判断带来的维护问题。该方案实现了资源的高效复用,同时支持灵活配置多种车型组合,为汽车行业多车型共平台开发提供了可扩展的技术实现。

shusuanly的博客 469

【干货】C#自定义特性(Attribute)讲解与实际应用

C#特性特性(attribute)是被指定给某一声明的一则附加的声明性信息。特性具有以下属性:特性可向程序中添加元数据。元数据是有关在程序中定义的类型的信息。所有的 .NET 程序集都包...

Vaccae的博客 2446

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Net中Attribute特性的高级使用及自定义验证实现

好久没写博客了,今天在百忙之中抽空来写篇文章,记录一下最近深入学习Attribute特性的笔记及心得。~~ 一、什么是特性? 特性(Attribute)是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([ ])来描述的。 特性(Attribute)...

weixin_30488313的博客 627

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

C# 特性(Attribute)

Obsolete.Net 框架允许创建自定义特性,用于存储声明性的信息,且可在运行时被检索。该信息根据设计标准和应用程序需要,可与任何目标元素相关。声明自定义特性构建自定义特性在目标程序元素上应用自定义特性通过反射访问特性最后一个步骤包含编写一个简单的程序来读取元数据以便查找各种符号。元数据是用于描述其他数据的数据和信息。该程序应使用反射来在运行时访问特性。我们将在下一章详细讨论这点。一个新的自定义特性应派生自类。例如:// 一个自定义特性 BugFix 被赋给类及其成员。

q45364926的博客 1790

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

C# 的特性 Attribute(学习心得 28)

特性(Attribute):用于,在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的 行为信息 的 声明性标签。 您可以通过使用 特性 向程序添加 声明性信息 。 一个 声明性标签 是通过放置在它所应用的元素前面的方括号([ ])来描述的。 特性(Attribute)用于添加 元数据,如编译器指令和注释、描述、方法、类等其他信息。 .Net 框架提供了两种类型的特性:预定义特性和自定义特性。 文章目录一、规定特性(Attribute)二、预定义特性(Attribute)2.1 Attribut

AItrust的博客 310

Attribute(一)——预定义特性

在项目中接触到了Attribute,那么什么是Attribute,有些什么作用呢?这里来了解一下。   一、什么是Attribute Attribute 类将预定义的系统信息或用户定义的自定义信息与目标元素相关联。目标元素可以是程序集、类、构造函数、委托、枚举、事件、字段、接口、方法、可移植可执行文件模块、参数、属性 (Property)、返回值、结构或其他属性 (Attribute)

littlecolor 2440

c#学习<三>:特性

特性(Attribute) 用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([ ])来描述的。 特性(Attribute)用于添加元数据,如编译器指令和注释、描述、方法、类等其他信息。功能类似JAVA中的注解(Annotation)。 约定 所有...

ahhawox560566的博客 131

【Unity】Unity C#基础(十二)特性Attribute、反射Reflection

特性 常用特性 自定义特性 更多内容请查看总目录【Unity】Unity学习笔记目录整理

一个普普通通的游戏开发者 4881

C# Attribute 特性 的用处举例

**特性(Attribute)是用来 向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([ ])来描述的。 特性(Attribute)用于添加元数据,如编译器指令和注释、描述、方法、类等其他信息。所以要获取某个类的特性,需要通过反射实现。**1、自定义一个 CheckCodeAttribute [AttributeUsage(AttributeTargets.Cl...

weixin_42339460的博客 1449

.Net Attribute 特性 自定义特性(二)

在实际开发中,我们经常看到如MVC中标记在方法上的 [HttpGet] [HttpPost][HttpDelete][HttpPut] ,序列化时标记在类上的 [Serializable] ,使用EF标记属性的 [Key] ,使用特性的地方随处可见。二次升级已完成,看看代码,瞬间心情舒畅。细心的朋友会发现,校验返回的都是true跟false,每次遇到校验不通过的字段后下面的都不再校验了,想要返回所有未校验通过的字段,并告诉调用者,一次性把所有字段都按照格式填好,这样才是我们想要的效果。

lwpoor123的博客 1533
上一篇: delegate(委托) -- event(事件) 基础应用
下一篇: IEnumerator 枚举器的使用
**启程**
博客等级 码龄6年 49粉丝 52原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值