C#特性:从自定义一个特性开始,谈谈什么是特性
作为C#新手中的一员,我刚开始接触特性时,那真是一脸冏逼啊,怎么想怎么查资料都没弄明白它到底是个什么东西,有的入门教程甚至都没讲特性和反射这些概念!相信很多人第一次接触到特性就是关于系列化的知识了。
官方概述:
特性提供功能强大的方法,用以将元数据或声明信息与代码(程序集、类型、方法、属性等)相关联。 特性与程序实体关联后,即可在运行时使用名为“反射”的技术查询特性。
先弄明白一点,一个特性,如Serializable,他其实就是一个类,定义方式跟类一样,且所有特性都是直接或间接继承自Attribute基类。
自定义一个特性
下面就来自定义一个特性MyAttribute
[AttributeUsage(AttributeTargets.Class,AllowMultiple=false,Inherited=false)]
public class MyAttribute : Attribute //类名是特性的名称
{
public float Version;//命名参数
private string Name;
public MyAttribute(string name) //name为定位参数
{
this.Name = name;
this.Version = 1.0f;
}
}
如何创建一个自定义特性:
- 一个自定义特性类必须直接或间接继承自System.Attribute特性类
- 为该自定义特性类指定System.AttributeUsage特性,并指定限制参数(枚举System.AttributeTargets)和可选的AllowMultiple、Inherited命名参数),AttributeUsage 的命名参数 AllowMultiple是否允许多次使用在同一目标上。Inherited命名参数表示是否同时应用于派生类型或重载版本。
- 类名是特性的名称。
- 构造函数的参数是自定义特性的定位参数(应用该特性时必须放在参数列表的最前面),也可以是无参构造函数(如
[Serializable])。 - 任何公共的读写字段或属性都是可选的命名参数。
- 如果特性类包含一个属性,则该属性必须为 读写属性。
应用特性
下面来应用该特性:
[My("srf", Version = 1.2f)]
class Test11
{
public float n;
public Test11()
{
}
public void PrintName()
{
}
}
应用特性[My("srf", Version = 1.2f)]其实是对构造函数的调用来实例化一个特性类。
根据约定,所有特性名称都以单词“Attribute”结束。 如可系列化标记特性Serializable,它的全称为SerializableAttribute,在代码中使用特性时,不需要指定 attribute 后缀,以上代码中同样只需要My来代表MyAttribute特性。
关联特性
利用反射的原理,关联特性类与目标类型(反射:主要利用Type类的属性和方法来获得一个目标类型的类型信息对象,然后根据该对象可以得到目标类型的信息,如它的字段、属性、方法名、类名等,有了这些信息,下一步就可以为所欲为了,可以还原该类型,即反系列化,甚至创建一个新类型)
如下代码:
//1.判断Test11类定义时,是否应用了该特性
if (typeof(Test11).IsDefined(typeof(MyAttribute),false))
{
//2.获得该特性对象,之后就可以访问它的成员(元数据)
MyAttribute attribute = (MyAttribute)Attribute.GetCustomAttribute(typeof(Test11), typeof(MyAttribute));
attribute.Version = 1.3f;
}
当编译器发现一个特性应用到一个目标,并发生关联时:
- 首先会把"Attribute"追加到特性的名称(若使用了简写),形成完整的特性类名
- 然后在其所有引入的命名空间中搜索该特性类,若找不到该类或它与目标不匹配,则产生编译错误
- 检查传递给特性的参数,并查找该特性中带定位参数的构造函数(或无参构造函数)和其它可选的命名参数(特性类的公共字段、属性),若找到匹配的构造函数,则实例化该特性类,编译器还会把目标类型的元数据传递给程序集,反射可以从程序集中读取元数据,找不到则产生编译错误。
关联代码可以定义在目标类型内部:
[My("srf", Version = 1.2f)]
class Test11
{
public float n;
public Test11()
{
}
public void PrintName()
{
//1.判断是否应用了该特性
if (this.GetType().IsDefined(typeof(MyAttribute),false))
{
//2.获得该特性对象,之后就可以访问它的成员
MyAttribute attribute = (MyAttribute)Attribute.GetCustomAttribute(typeof(Test11), typeof(MyAttribute));
attribute.Version = 1.3f;
this.n = attribute.Version;
}
}
}
.NET预定义特性
至于.NET预定义特性的实现原理,我没研究过,大概类似自定义特性吧,就比如系列化特性SerializableAttribute,实现原理我想大概是这样:应用[Serializable]时给目标做一个“标记”,在.NET内置程序集的某个地方判断该目标类型是否应用了该特性,然后决定是否进行系列化操作。
总之,特性其实没那么难,它就是一个类,或者说是一个用来服务于其它类型的类,一个目标类型应用了一个特性,那么这个目标类型就可以享受该特性提供的服务了!
以上纯属个人对特性的理解,有不对的地方请前辈们务必指正,以免误导!
C#特性:从自定义一个特性开始,谈谈什么是特性的更多相关文章
- Java高级特性--自定义一个StringBuilder的类
案例讲解--自定义一个StringBuilder的类 一:案例设计介绍 自义一个M定yStringBuilder来实现StringBuilder的功能 二:案例设计 实现append()方法追加字符串 ...
- 一个全新的Vue拖拽特性实现:“移动”部分
关于拖拽 CabloyJS提供了完备的拖拽特性,可以实现移动和调整尺寸两大类功能,这里对移动的开发进行阐述 关于调整尺寸的开发,请参见:拖拽:调整尺寸 演示 开发步骤 下面以模块test-party为 ...
- 一个列子演示vs2010 c++新特性
近日托安装雪豹的"福",格了XP装了win7,前段时间看了C++0X标准以及VS2010诱人的新特性,不禁心痒痒在线安装了VS2010,然后手写了这个列子用来测试新增的特性. st ...
- Sping框架的IOC特性 悲观锁、乐观锁 Spring的AOP特性
Sping框架的IOC特性 IOC(Inversion of Control):控制反转 以下以课程与老师的安排来介绍控制反转. 一个合理的课程编排系统应该围绕培训的内容为核心,而不应该以具体的培训老 ...
- ASP.NET Core 6框架揭秘实例演示[28]:自定义一个服务器
作为ASP.NET Core请求处理管道的"龙头"的服务器负责监听和接收请求并最终完成对请求的响应.它将原始的请求上下文描述为相应的特性(Feature),并以此将HttpCont ...
- KestrelServer详解[3]: 自定义一个迷你版的KestrelServer
和所有的服务器一样,KestrelServer最终需要解决的是网络传输的问题.在<网络连接的创建>,我们介绍了KestrelServer如何利用连接接听器的建立网络连接,并再次基础上演示了 ...
- 事务、事务特性、事务隔离级别、spring事务传播特性
事务.事务特性.事务隔离级别.spring事务传播特性 1.什么是事务: 事务是程序中一系列严密的操作,所有操作执行必须成功完成,否则在每个操作所做的更改将会被撤销,这也是事务的原子性(要么成功, ...
- SpringMVC 自定义一个拦截器
自定义一个拦截器方法,实现HandlerInterceptor方法 public class FirstInterceptor implements HandlerInterceptor{ /** * ...
- jQuery Validate 表单验证插件----自定义一个验证方法
一.下载依赖包 网盘下载:https://yunpan.cn/cryvgGGAQ3DSW 访问密码 f224 二.引入依赖包 <script src="../../scripts/j ...
随机推荐
- IOS开发创建开发证书及发布App应用(九)——等待审核(审核几种状态)
以下是App应用的几种状态,如果看不到英文,建议复制到网站翻译一下就行,意思差不多能明白的 以上整套流程是在2013年写的,可能有些地方已经不太一样了,只是给大家做一下参考,毕竟再怎么改大概流程还是差 ...
- linux下的权限控制
终于还是要弄服务器了,这是多年前用fedora的时候整理的,也贴出来,顺便也再复习一下. 先来了解一下文件属性,在shell环境里输入:ls -l 可以查看当前目录文件.如:drwxr-xr-x. 1 ...
- 神奇的框架插件jquery layer
layer 的这个相册功能是不是很炫酷,是滴,这就是layer,只要添加一个layerjs就行了 //Javascript代码 layer.photos({ photos: '#photosDemo' ...
- C语言指针基础
新手在C语言的学习过程中遇到的最头疼的知识点应该就是指针了,指针在C语言中有非常大的用处.下面我就带着问题来写下我对于指针的一些理解. 指针是什么? 指针本身是一个变量,它存储的是数据在内存中的地址 ...
- XJOI1689相连的城市
相连的城市 n个城市中,某些城市间有道路互相连接.给出与每个城市相邻的城市有多少个,请输出城市间的邻接矩阵. 输入格式: 第一行输入一个正整数n,表示城市的个数. 第二行输入n个用空格隔开的非负整数, ...
- AngularJS1.X学习笔记1-整体看看
听说 明天是愚人节,这与我有什么关系呢!我可 不想被愚弄,但是但是,我这么笨怎么才能不被愚弄呢?左思右想,我决定从现在开始闭关,闭关干啥哩?学习!学习AngularJS.以前学习过Angular的,不 ...
- Snapman设计中的思考
Snapman主页:http://www.snapman.xyz 原文链接地址:http://www.snapman.xyz/newsitem/277785310 feiren工作室主要研究人类 ...
- mysql自动备份删除5天前的备份
1.查看磁盘空间情况: # df -h 2.创建备份目录: 上面我们使用命令看出/home下空间比较充足,所以可以考虑在/home保存备份文件: cd /home mkdir backup cd ba ...
- JavaScript基础学习(三)—数组
一.数组简介 JavaScript数组的每一项都可以保存任何类型的数据,也就是说数组的第一个位置保存字符串,第二个位置可以保存数值,第三个位置可以保存对象,而且数组的大小是可以动态调整的,即可 ...
- Mac OS平台下应用程序安装包制作工具Packages的使用介绍(补充)
上一篇:Mac OS平台下应用程序安装包制作工具Packages的使用介绍 补充说明 上一篇文章中介绍了如何使用Packages如何创建mac下的安装包.但是这样制作出来的安装包只能安装到系统的文件路 ...