使用特性(Attribute)可以将描述程序集的信息和描述程序集中任何类型和成员的信息添加到程序集的元数据和IL代码中,程序可以在运行时通过反射获取到这些信息;

  一、通过直接或间接的继承自抽象类System.Attribute可以创建自定义的特性类,自定义的特性类必须声明为公共类,命名一般使用Attribute结尾以保证可读性,自定义特性可以附加到大多数元素声明中,也可以使用特性System.AttributeUsage(该特性只能用于特性类声明)指定该特性所能生效的范围及其它特性特征参数:

[AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = true)]
//其中,枚举组合AttributeTargets指定该特性生效的范围,默认为All即所有范围;
//布尔值Inherited指定应用该特性的成员在派生类中是否会继承该特性,默认为true;
//布尔值AllowMultiple指定能否为同一个元素指定多个此特性,默认为false
public class MyselfAttribute : Attribute
{
public string ClassName { get; private set; }
public string Author; public MyselfAttribute(string className)
{
this.className = className;
}
}

  其中特性类的构造函数中的参数称为位置参数(Positional Parameters),类中的其他公共字段和属性称为命名参数(Named Parameter), 通常情况下,将所有必选的参数定义为位置参数,将所有可选的参数定义为命名参数;特性类和普通类一样可以进行构造函数的重载以适应各种情况下初始化参数的组合使用;

  二、使用特性时,通过方括号[]将特性名称括起来,并置于使用该特性的元素声明的上方或前方以指定特性,使用时可以省略Attribute后缀,根据想要初始化时调用特性类构造函数的不同,需要将该构造函数所需的参数(即位置参数)的值按照顺序传入,还可以选择是否指定命名参数的值,命名参数的值通过赋值运算符=显式指定:

[Myself("MyClass", Author = "Me")]
//这个声明在概念上等效于:
//MyselfAttribute myselfObj = new MyselfAttribute("MyClass");
//myselfObj.Author = "Me";
//[Myself("MyClass", Author = "You")] //特性Myself可以对同一元素指定多次
//也可以将多个特性合并在一个方括号里:
//[Myself("MyClass", Author = "Me"), Myself("MyClass", Author = "You")]
public class MyClass
{
public void MyFunc([Myself("MyParameter")]int myNum) //在方法参数列表中给参数指定特性
{
//do…
}
}

  经过编译后,在元数据中查看到的类型定义中的特性信息:

TypeDef # ()
-------------------------------------------------------
TypDefName: MyClass ()
Flags : [Public] [AutoLayout] [Class] [AnsiClass] [BeforeFieldInit] ()
Extends : [TypeRef] System.Object
Method # ()
-------------------------------------------------------
MethodName: MyFunc ()
Flags : [Public] [Virtual] [HideBySig] [NewSlot] (000001c6)
RVA : 0x00002050
ImplFlags : [IL] [Managed] ()
CallCnvntn: [DEFAULT]
hasThis
ReturnType: Void
Arguments
Argument #: I4
Parameters
() ParamToken : () Name : myNum flags: [none] ()
CustomAttribute # (0c000003)
-------------------------------------------------------
CustomAttribute Type:
CustomAttributeName: MyselfAttribute :: instance void .ctor(class System.String)
Length:
Value : 0b 4d 6d > MyParameter <
ctor args: ("MyParameter") Method # ()
-------------------------------------------------------
MethodName: .ctor ()
Flags : [Public] [HideBySig] [ReuseSlot] [SpecialName] [RTSpecialName] [.ctor] ()
RVA : 0x0000205a
ImplFlags : [IL] [Managed] ()
CallCnvntn: [DEFAULT]
hasThis
ReturnType: Void
No arguments. CustomAttribute # (0c000015)
-------------------------------------------------------
CustomAttribute Type:
CustomAttributeName: MyselfAttribute :: instance void .ctor(class System.String)
Length:
Value : 4d 6c 0e > MyClass T A<
: 6f 4d >uthor Me <
ctor args: ("MyClass")

  在IL代码中查看到的类型定义中的特性信息:

  三、系统预定义的一些常用特性:

  四、特性通常配合反射起作用,在指定的时机通过反射获得自定义特性并对其进行操作,具体内容在下一章中介绍;


如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的认可是我写作的最大动力!

作者:Minotauros
出处:https://www.cnblogs.com/minotauros/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

详解C#特性和反射(一)的更多相关文章

  1. EF+LINQ事物处理 C# 使用NLog记录日志入门操作 ASP.NET MVC多语言 仿微软网站效果(转) 详解C#特性和反射(一) c# API接受图片文件以Base64格式上传图片 .NET读取json数据并绑定到对象

    EF+LINQ事物处理   在使用EF的情况下,怎么进行事务的处理,来减少数据操作时的失误,比如重复插入数据等等这些问题,这都是经常会遇到的一些问题 但是如果是我有多个站点,然后存在同类型的角色去操作 ...

  2. 详解C#特性和反射(四)

    本篇内容是特性和反射的最后一篇内容,前面三篇文章: 详解C#特性和反射(一) 详解C#特性和反射(二) 详解C#特性和反射(三) 一.晚期绑定(Late Binding)是一种在编译时不知道类型及其成 ...

  3. 详解C#泛型(二) 获取C#中方法的执行时间及其代码注入 详解C#泛型(一) 详解C#委托和事件(二) 详解C#特性和反射(四) 记一次.net core调用SOAP接口遇到的问题 C# WebRequest.Create 锚点“#”字符问题 根据内容来产生一个二维码

    详解C#泛型(二)   一.自定义泛型方法(Generic Method),将类型参数用作参数列表或返回值的类型: void MyFunc<T>() //声明具有一个类型参数的泛型方法 { ...

  4. 详解C#特性和反射(三)

    类型信息(Type Information)用来表示类型声明的信息,通过抽象基类System.Type的实例存储这些信息,当使用反射时,CLR获取指定类型的Type对象,通过这个对象即可访问该类型的任 ...

  5. 详解C#特性和反射(二)

    使用反射(Reflection)使得程序在运行过程中可以动态的获取对象或类型的类型信息,然后调用该类型的方法和构造函数,或访问和修改该类型的字段和属性:可以通过晚期绑定技术动态的创建类型的实例:可以获 ...

  6. 【转】详解C#中的反射

    原帖链接点这里:详解C#中的反射   反射(Reflection) 2008年01月02日 星期三 11:21 两个现实中的例子: 1.B超:大家体检的时候大概都做过B超吧,B超可以透过肚皮探测到你内 ...

  7. 详解Java8特性之新的日期时间 API

    详解Java8特性之新的日期时间 API http://blog.csdn.net/timheath/article/details/71326329 Java8中时间日期库的20个常用使用示例 ht ...

  8. Git使用总结 Asp.net生命周期与Http协议 托管代码与非托管代码的区别 通过IEnumerable接口遍历数据 依赖注入与控制反转 C#多线程——优先级 AutoFac容器初步 C#特性详解 C#特性详解 WPF 可触摸移动的ScrollViewer控件 .NET(C#)能开发出什么样的APP?盘点那些通过Smobiler开发的移动应用

    一,原理 首先,我们要明白Git是什么,它是一个管理工具或软件,用来管理什么的呢?当然是在软件开发过程中管理软件或者文件的不同版本的工具,一些作家也可以用这个管理自己创作的文本文件,由Linus开发的 ...

  9. 详解C#中的反射

    反射(Reflection) 2008年01月02日 星期三 11:21 两个现实中的例子:1.B超:大家体检的时候大概都做过B超吧,B超可以透过肚皮探测到你内脏的生理情况.这是如何做到的呢?B超是B ...

随机推荐

  1. HDU2473 Junk-Mail Filter 并查集

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - HDU2473 题意概括 一堆点. 要你支持合并两组点.分离某组点中的一个,这两种操作. 点数<=100 ...

  2. 动态产生DataSource------待整理

    1. https://www.cnblogs.com/wsss/p/5475057.html https://www.cnblogs.com/jiligalaer/p/5418874.html htt ...

  3. rocketMQ基本架构简介

    1.RocketMQ 简介: RocketMQ前身是阿里研发的一个队列模型的消息中间件,后开源给apache基金会成为了apache的顶级开源项目,具有高性能.高可靠.高实时.分布式特点. 2.Roc ...

  4. vuex数据持久化存储

    想想好还是说下vuex数据的持久化存储吧.依稀还记得在做第一个vue项目时,由于刚刚使用vue,对vue的一些基本概念只是有一个简单的了解.当涉及到非父子组件之间通信时,选择了vuex.只是后来竟然发 ...

  5. Servlet与HTTP介绍学习

    http介绍:http是一套规范,一种网络数据交互的标准协议,不同的语言,不同的数据想要实现合理的数据交互(例如:浏览器和服务器数据交互),就得按照他所规定的协议来,这样就会形成标准的(大家都认识的) ...

  6. Codeforces Round #514 (Div. 2)

    目录 Codeforces 1059 A.Cashier B.Forgery C.Sequence Transformation D.Nature Reserve(二分) E.Split the Tr ...

  7. full GC触发的条件

    full GC触发的条件除直接调用System.gc外,触发Full GC执行的情况有如下四种.1. 旧生代空间不足旧生代空间只有在新生代对象转入及创建为大对象.大数组时才会出现不足的现象,当执行Fu ...

  8. BZOJ1330 : Editing a Book

    注意到答案不超过$5$,因此可以考虑BFS求出距离起始态或者终止态不超过$2$的所有状态. 设它们到起始态.终止态的距离分别为$f[S],g[S]$,则$ans=\min(5,f[S]+g[S])$. ...

  9. 未能加载文件或程序集“Benlai.SOA.Framework.Common, Version=1.4.0.0, Culture=neutral, PublicKeyToken=null”或它的某一个依赖项。系统找不到指定的文件。

    未能加载文件或程序集“Benlai.SOA.Framework.Common, Version=1.4.0.0, Culture=neutral, PublicKeyToken=null”或它的某一个 ...

  10. aps.net手写验证模型的方法

    /// <summary> /// 基础验证类 /// </summary> public class BaseValidator { /// <summary> ...