使用特性(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. 【开源小软件 】Bing每日壁纸 让桌面壁纸保持更新

    发布一个开源小软件,Bing每日壁纸. 该小软件可以自动获取Bing的精美图片设置为壁纸,并且支持随机切换历史壁纸,查看壁纸故事. 欢迎大家下载使用,点star!有问题请留言或者提issue. 开源地 ...

  2. Codeforces 269C Flawed Flow (看题解)

    我好菜啊啊啊.. 循环以下操作 1.从队列中取出一个顶点, 把哪些没有用过的边全部用当前方向. 2.看有没有点的入度和 == 出度和, 如果有将当前的点加入队列. 现在有一个问题就是, 有没有可能队列 ...

  3. 033 关于YARN的HA

    一:准备 1.规划 namenode               namenode ZKFC ZKFC journalnode        journalnode               jou ...

  4. sklearn.preprocessing.LabelEncoder的使用

    在训练模型之前,我们通常都要对训练数据进行一定的处理.将类别编号就是一种常用的处理方法,比如把类别"男","女"编号为0和1.可以使用sklearn.prepr ...

  5. Machine Learning 学习笔记1 - 基本概念以及各分类

    What is machine learning? 并没有广泛认可的定义来准确定义机器学习.以下定义均为译文,若以后有时间,将补充原英文...... 定义1.来自Arthur Samuel(上世纪50 ...

  6. FastAdmin 的上传代码在哪里?

    FastAdmin 的上传代码在哪里? FastAdmin 默认是通过 Ajax 上传到本地. 使用 admin/ajax/upload 方式返回 url. 代码文件地址在 application\a ...

  7. HDU 2602 Bone Collector 骨头收集者【01背包】

    题目链接:https://vjudge.net/contest/103424#problem/A 题目大意: 第一行输入几组数据,第二行第一个数字代表物体个数,第二个数代表总体积.需要注意的是,第三排 ...

  8. Java并发编程快速学习

    上周的面试中,被问及了几个关于Java并发编程的问题,自己回答的都不是很系统和全面,可以说是"头皮发麻",哈哈.因此果断购入<Java并发编程的艺术>一书,学习后的体会 ...

  9. 【Ray Tracing in One Weekend 超详解】 光线追踪1-5

    一天一篇,今天来学习第7章 (散射)漫反射材质 Chapter7: Diffuse Materials Preface 从这一章开始,我们将通过光线追踪制作一些逼真的材质. 我们将从漫射(磨砂)材料开 ...

  10. JavaEE - 20181225

    作者:沈世钧链接:https://www.zhihu.com/question/305924723/answer/557800752来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...