C#特性(属性)Attribute
先明确一个概念:
元数据。.NET中元数据是指程序集中的命名空间、类、方法、属性等信息。这些信息是可以通过Reflection读取出来的。
再来看个例子:
#define BUG //#define NOBUG using System; using System.Diagnostics;namespace AttributeExample {public static class AttributeTest{[Conditional("BUG")]public static void OutputDebug(string msg){Console.WriteLine(msg + " : bug");}[Conditional("NOBUG")]public static void OutputMessage(string msg){Console.WriteLine(msg + " : no bug");}}class Program{static void Main(string[] args){AttributeTest.OutputDebug("Function");AttributeTest.OutputMessage("Function");Console.Read();}} }
运行结果:
将#define BUG注释掉,#define NOBUG的注释取消,重新运行的结果如下:
那么可以理解为,上述代码中的[Conditional()]起到了条件的作用。这就是一种特性。
特性是用于在运行时传递程序中各种元素(类、方法、结构、枚举等)的行为信息的声明性标签。可以通过使用特性向程序中添加声明性信息。这些信息添加到了元数据中。.NET框架中的特性包括Common Attributes和Custom Attributes。其中Common Attributes包括Global Attributes, Obsolete Attributes, Conditional Attributes, Caller Info Attributes。
Common Attributes
- Global Attributes 全局特性,应用于整个程序集。置于using后代码最上端。全局特性提供一个程序集的信息,分为三种类别:
- Assembly identity attributes 程序集标识符特性。name, version, and culture这三个特性用于确定一个程序集的标识符。可以查看一下项目中Properties下面的AssemblyInfo.cs文件。
- Informational attributes 信息特性,提供一些与公司或产品相关的信息,包括AssemblyProductAttribute,AssemblyTrademarkAttribute等。
- Assembly manifest attributes 程序集清单特性。包括title, description, default alias, and configuration。
- Conditional Attributes 标记了一个条件方法,其执行依赖于指定的预处理标识符(#define),实例就是上面那个。条件特性可以同时使用多个。比如[Conditional("A"), Conditional("B")]。
- Obsolete Attributes 标记了不应被使用的程序实体。它可以让您通知编译器丢弃某个特定的目标元素。其语法表示为:[Obsolete(message)]、[Obsolete(message, iserror)]
其中,message是一个string,描述项目为什么过时以及该替代使用什么;iserror是一个bool,如果为true,编译器应该把项目的使用当做一个错误,默认值是false,此时编译器生成一个警告。比如下面的例子:
using System; using System.Diagnostics;namespace AttributeExample {class Program{[Obsolete("Don't use OldMethod, use NewMethod instead", true)]static void OldMethod(){Console.WriteLine("It is the old method");}static void NewMethod(){Console.WriteLine("It is the new method");}static void Main(string[] args){OldMethod();Console.Read();}} }
这时程序无法编译,显示如下的错误:
- Caller Info Attributes 通过使用该特性,可以获取调用某个方法的调用者的信息。比如代码的文件路径、代码的行等。比如下面所示的代码。
using System; using System.Runtime.CompilerServices;namespace AttributeExample {class Program{public static void DoSomething(){TraceMessage("Something happened.");}public static void TraceMessage(string message,[CallerMemberName] string memberName = "",[CallerFilePath] string sourceFilePath = "",[CallerLineNumber] int sourceLineNumber = 0){Console.WriteLine("message: " + message);Console.WriteLine("member name: " + memberName);Console.WriteLine("source file path: " + sourceFilePath);Console.WriteLine("source line number: " + sourceLineNumber);}static void Main(string[] args){DoSomething();Console.Read();}} }
运行结果如图所示:
Custom Attributes
.NET框架允许创建自定义特性,用于存储声明性的信息,且可在运行时被检索。该信息根据设计标准和应用程序需要,可与任务目标元素相关。创建并使用自定义特性包含四个步骤:
1. 声明自定义特性
一个新的自定义特性应派生自System.Attribute类,比如:
// 声明名为FirstAttribute的自定义特性 [AttributeUsage(AttributeTargets.Class, Inherited =false)]class FirstAttribute : Attribute { } // 声明名为SecondAttribute的自定义特性[AttributeUsage(AttributeTargets.Class)]class SecondAttribute : Attribute { } // 声明名为ThirdAttribute的自定义特性[AttributeUsage(AttributeTargets.Class, AllowMultiple =true)]class ThirdAttribute : Attribute { }
又比如:
// 声明名为CustomAttribute的自定义特性 [AttributeUsage(AttributeTargets.Class|AttributeTargets.Constructor|AttributeTargets.Field|AttributeTargets.Method|AttributeTargets.Property,AllowMultiple =true)]public class CustomAttributes : System.Attribute{}
2.构建自定义特性
上面已经声明了一个名为CustomAttribute的自定义特性,现在构建这个特性。该特性将存储调试程序获得的信息,包括:bug的代码编号、辨认该bug的开发人员名字、最后一次审查该代码的日期以及一个存储了开发人员标记的字符串消息。
CustomAttribute类将带有三个用于存储前三个信息的私有属性和一个用于存储消息的公有属性。因此bug编号、开发人员名字和审查日期将是CustomAttribute类的必需的定位(positional)参数,消息将是一个可选的命名(named)参数。每个特性必须至少有一个构造函数。必需的定位参数应通过构造函数传递,如下面的代码所示:
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Constructor|AttributeTargets.Field|AttributeTargets.Method|AttributeTargets.Property,AllowMultiple =true)]public class CustomAttributes : System.Attribute{public int BugNo { get; }public string Developer { get; }public string LastReview { get; }public string Message { get; set; }public CustomAttributes(int BugNo, string Developer, string LastReview){this.BugNo = BugNo;this.Developer = Developer;this.LastReview = LastReview;}}
3.在目标程序元素上应用自定义特性
通过把特性放置在紧接着它的目标之前,来应用该特性:
[CustomAttributes(45,"Zara Ali","12/8/2012", Message ="Return type mismatch")][CustomAttributes(49,"Nuha Ali","10/10/2012",Message ="Unused variable")]class Rectangle{protected double length;protected double width;public Rectangle(double length, double width){this.length = length;this.width = width;}[CustomAttributes(55,"Zara Ali","19/10/2012", Message ="Return type mismatch")]public double GetArea(){return length * width;}[CustomAttributes(56,"Zara Ali", "19/10/2012")]public void Display(){Console.WriteLine("Length: {0}", length);Console.WriteLine("Width: {0}", width);Console.WriteLine("Area: {0}", GetArea());}}
4.通过反射访问特性
别忘了使用using System.Reflection;
class ExecuteRectangle{static void Main(string[] args){Rectangle r = new Rectangle(4.5, 7.5);r.Display();object[] attrs = r.GetType().GetCustomAttributes(false);// 遍历Rectangle类的特性foreach(Attribute attr in attrs){CustomAttributes attribute = (CustomAttributes)attr;if(null != attribute){Console.WriteLine("Bug no: {0}", attribute.BugNo);Console.WriteLine("Developor: {0}", attribute.Developer);Console.WriteLine("Last Reviewed: {0}", attribute.LastReview);Console.WriteLine("Remarks: {0}", attribute.Message);}}// 遍历方法特性object[] methods = r.GetType().GetMethods();foreach(MethodInfo method in methods){foreach(object attribute in method.GetCustomAttributes(true)){CustomAttributes attr = attribute as CustomAttributes;if(null != attr){Console.WriteLine("Bug no: {0}, for Method: {1}", attr.BugNo, method.Name);Console.WriteLine("Developer: {0}", attr.Developer);Console.WriteLine("Last Reviewed: {0}", attr.LastReview);Console.WriteLine("Remarks: {0}", attr.Message);}}}Console.Read();}}
运行结果如图所示:
参考文献:
1.https://www.runoob.com/csharp/csharp-attribute.html
2.https://www.runoob.com/csharp/csharp-reflection.html
3.https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/attributes/
4.https://blog.csdn.net/xiaouncle/article/details/70216951
转载于:https://www.cnblogs.com/larissa-0464/p/11417337.html
C#特性(属性)Attribute相关推荐
- python特性 property_python之中特性(attribute)与属性(property)有什么区别?
原博文 2020-07-28 04:20 − 属性(property)是一种特殊的特性(attribute). 如下,我们定义了一个圆圈类(circle),圆圈嘛,自然就有直径(diameter)和半 ...
- C# 特性(Attribute)学习。
特性(attribute)是被指定给某一声明的一则附加的声明性信息. 在C#中,有一个小的预定义特性集合.在学习如何建立我们自己的定制特性(custom attributes)之前,我们先来看看在我们 ...
- Swfit 常用特性(Attribute)关键字
Swfit 常用特性(Attribute)关键字 Swift中的Attribute相当于Java中的注解,但是可惜的是目前Swift不支持自定义Attribute Swfit的特性关键字一般用于声明或 ...
- C# 特性(Attribute)学习
特性(attribute)是被指定给某一声明的一则附加的声明性信息. 在C#中,有一个小的预定义特性集合.在学习如何建立我们自己的定制特性(custom attributes)之前,我们先来看看在我们 ...
- 特性(Attribute)
特性(Attribute) 常用的系统特性 Serializable:常用于标记类,表示可被序列化 Nonserialized :不允许序列化,在被标注为Serializable序列化的类中,某字段前 ...
- C#之特性(Attribute)
参考:https://www.runoob.com/csharp/csharp-attribute.html 特性(Attribute)是用于在运行时传递程序中各种元素(比如类.方法.结构.枚举.组件 ...
- C#特性(Attribute)讲解
1.特性的介绍与使用 特性(Attribute)是用于在运行时传递程序中各种元素(比如类.方法.结构.枚举.组件等)的行为信息的声明性标签.您可以通过使用特性向程序添加声明性信息.一个声明性标签是通过 ...
- 参数(parameter)和属性(attribute)的区别
参数parameter 属性attribute 区别 来源 parameter来源于用户提交的http请求.以Get方法提交的请求来源于url:以Post提交的请求来源于请求体 web资源中设置的属性 ...
- 3 QM配置-质量计划配置-编辑特性属性的选择集
业务背景:编辑特性属性的选择集 事务码:QS51 SPRO路径:SPRO->质量管理->质量计划->基本信息->目录->编辑检验特征目录->编辑选择集 第1步,SP ...
- 2 QM配置-质量计划配置-编辑特性属性的代码组和代码
业务背景:编辑特性属性的代码组和代码 事务码:QS41 SPRO路径:SPRO->质量管理->质量计划->基本信息->目录->编辑检验特征目录->编辑代码组和代码 ...
最新文章
- 机器学习-线性回归LinearRegression
- 贪心 ---- Codeforces Global Round 8,B. Codeforces Subsequences[贪心,贪的乘法原理]
- 程序员的“认知失调”
- 复杂业务如何保证Flutter的高性能高流畅度?
- 记录0.7.1版本的seata批量保存会报错的情况
- centos yum install redis
- php目的,php umask(0)的目的是什么
- 2012黑龙江省赛J题-最小均值圈
- 桌面计算机未响应怎么办,资源管理器未响应怎么办
- 地理信息系统(汤国安)重点整理与推导(第三章)
- Windows上安装PyV8
- 23篇大数据系列(三)sql基础知识(史上最全,建议收藏)
- excel打不开_mac版excel死机该如何恢复?
- msl3等级烘烤时间_msl湿敏等级对应表
- SQL Server使用SUM(求和)函数
- 互联网思维——简约思维
- 写一个蛇型数组(蛇形填数)
- 鸿蒙系统首批机型,鸿蒙系统名单确认,麒麟9000机型首批,众多机型要说再见!...
- 标志寄存器——标志位
- win7安装解压版mysql_win7安装解压缩版mysql 5.7.19和卸载后重新安装