元数据,就是C#中封装的一些类,无法修改.类成员的特性被称为元数据中的注释.

1、什么是特性

  1)属性与特性的区别

属性(Property):属性是面向对象思想里所说的封装在类里面的数据字段,Get,Set方法。

特性(Attribute):  官方解释:特性是给指定的某一声明的一则附加的声明性信息。 允许类似关键字的描述声明。它对程序中的元素进行标注,如类型、字段、方法、属性等。从.net角度看,特性是一种 类,这些类继承于System.Attribute类,用于对类、属性、方法、事件等进行描述,主要用在反射中。但从面向对象的级别看,其实Attribute是类型级别的,而不是对象级别。

Attributes和.net文件的元素据保存在一起,可以用来向运行时描述你的代码,或者在程序运行的时候影响程序的行为。

2、特性的应用

(1).net中特性用来处理多种问题,比如序列化、程序的安全特性、防止即时编译器对程序代码进行优化从而代码容易调试等等。

定植特性的本质上是一个类的元素上去添加附加信息,并在运行其通过反射得到该附加信息(在使用数据实体对象时经常用到)

(2)Attribute 作为编译器的指令时的应用

Conditional:起条件编译的作用,只有满足条件,才允许编译器对它的代码进行编译。一般在程序调试的时候使用

DllImport: 用来标记费.net的函数,表明该方法在一个外部的DLL中定义。

Obsolete: 这个属性用来标记当前的方法已经废弃,不再使用

注:Attribute是一个类,因此DllImport也是一个类,Attribute类是在编译的时候实例化,而不是像通常那样在运行时实例化。

CLSCompliant: 保证整个程序集代码遵守CLS,否则编译将报错。

 3、自定义特性

使用AttributeUsage,来控制如何应用新定义的特性

[AttributeUsageAttribute(AttributeTargets.All  可以应用到任何元素

,AllowMultiple=true, 允许应用多次,我们的定值特性能否被重复放在同一个程序实体前多次。

,Inherited=false,不继承到派生

)]

特性也是一个类,必须继承于System.Attribute类,命名规范为“类名”+Attribute。不管是直接还是间接继承,都会成为一个特性类,特性类的声明定义了一种可以放置在声明之上新的特性。

public class MyselfAttribute:System.Attribute

自定义特定:

  1. //限定特性类的应用范围
  2. [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field, AllowMultiple = true, Inherited = false)]
  3. //定制MsgAttribute特性类,继承于Attribute
  4. public class ClassMsgAttribute : Attribute
  5. {
  6. //定义_msg字段和Msg属性//Msg属性用于读写msg字段
  7. string _msg;
  8. public string Msg { get { return _msg; } set { _msg = value; } }
  9. public ClassMsgAttribute() { }
  10. //重载构造函数接收一个参数,赋值给_msg字段
  11. public ClassMsgAttribute(string s) { _msg = s; } 
  12. }

//限定特性类的应用范围
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Field, AllowMultiple = true, Inherited = false)]
//定制MsgAttribute特性类,继承于Attribute
public class ClassMsgAttribute : Attribute
{
//定义_msg字段和Msg属性//Msg属性用于读写msg字段
string _msg;
public string Msg { get { return _msg; } set { _msg = value; } }
public ClassMsgAttribute() { }
//重载构造函数接收一个参数,赋值给_msg字段
public ClassMsgAttribute(string s) { _msg = s; } 
}

调用:

  1. //在Person类上标记ClassMsg特性
  2. [ClassMsg(Msg = "这是关于人的姓名信息的类")]
  3. class Person
  4. {
  5. //在_name字段上应用ClassMsg特性
  6. [ClassMsg("这是存储姓名的字段")]
  7. string _name;
  8. //以下特性无法应用,因为MsgAttribute定义的特性只能用于类和字段
  9. //[ClassMsg("这是读写姓名字段的属性")]
  10. public string Name { get { return _name; } set { _name = value; } }
  11. }

//在Person类上标记ClassMsg特性
[ClassMsg(Msg = "这是关于人的姓名信息的类")]
class Person
{
//在_name字段上应用ClassMsg特性
[ClassMsg("这是存储姓名的字段")]
string _name;
//以下特性无法应用,因为MsgAttribute定义的特性只能用于类和字段
//[ClassMsg("这是读写姓名字段的属性")]
public string Name { get { return _name; } set { _name = value; } }
}

主函数的情况

  1. static void Main(string[] args)
  2. {
  3. //获取Person类的Type对象tp
  4. Type tp = Type.GetType("Person");
  5. //获取tp对象的特性数组,并将数组赋值给MyAtts
  6. object[] MyAtts = tp.GetCustomAttributes(false);
  7. //遍历并输出MyAtts数组子项的Msg属性
  8. foreach (ClassMsgAttribute m in MyAtts)
  9. {
  10. Console.WriteLine("Person类的特性:{0}", m.Msg);
  11. }

static void Main(string[] args)
{
//获取Person类的Type对象tp
Type tp = Type.GetType("Person");
//获取tp对象的特性数组,并将数组赋值给MyAtts
object[] MyAtts = tp.GetCustomAttributes(false);
//遍历并输出MyAtts数组子项的Msg属性
foreach (ClassMsgAttribute m in MyAtts)
{
Console.WriteLine("Person类的特性:{0}", m.Msg);
}

GetCustomAttributes用于获取程序集的特性,也就是这个程序集合中包含了多少个特性

继续来一个简单的例子来说明定制特性:

using System;

public class HelpAttribute: Attribute  //定制特性相当于一个类

{

//...

}

不管你是否相信,我们上面已经建立了一个定制特性,现在我们可以用它来装饰现有的类就好像我们使用的Obsolete attribute一样。

[Help()]

public class AnyClass

{

//...

}

注意:对于一个特性类使用Attribute后缀是一个惯例。然而,如果不添加编译器会自动添加匹配。

定义或控制特性的使用

AttributeUsage类是另外一个预定义特性类,它帮助我们控制我们自己的定制特性的使用。它描述一个定制特性如何被使用。

下面通过实例来探讨下AttributeUsage的三个属性

1)我们将会在刚才的Help特性前放置AttributeUsage特性以期待在它的帮助下控制Help特性的使用。  

  1. using System;
  2.   [AttributeUsage(AttributeTargets.Class), AllowMultiple = false,
  3.   Inherited = false ]
  4.   public class HelpAttribute : Attribute
  5.   {
  6.   public HelpAttribute(String Description_in)
  7.   {
  8.   this.description = Description_in;
  9.   }
  10.   protected String description;
  11.   public String Description
  12.   {
  13.   get
  14.   {
  15.   return this.description;
  16.   }
  17.   }
  18.   }

using System;
   [AttributeUsage(AttributeTargets.Class), AllowMultiple = false,
   Inherited = false ]
   public class HelpAttribute : Attribute
   {
   public HelpAttribute(String Description_in)
   {
   this.description = Description_in;
   }
   protected String description;
   public String Description
   {
   get
   {
   return this.description;
   }
   }
   }

先让我们来看一下AttributeTargets.Class。它规定了Help特性只能被放在class的前面。这也就意味着下面的代码将会产生错误:

  1. [Help("this is a do-nothing class")]
  2. public class AnyClass
  3. {
  4. [Help("this is a do-nothing method")] //error
  5. public void AnyMethod()
  6. {
  7. }
  8. }
  9. //编译器报告错误如下:  
  10. AnyClass.cs: Attribute 'Help' is not valid on this declaration type.
  11. It is valid on 'class' declarations only.   

   [Help("this is a do-nothing class")]
   public class AnyClass
   {
   [Help("this is a do-nothing method")] //error
   public void AnyMethod()
   {
   }
   }

   //编译器报告错误如下:  

   AnyClass.cs: Attribute 'Help' is not valid on this declaration type.
   It is valid on 'class' declarations only.   

我们可以使用AttributeTargets.All来允许Help特性被放置在任何程序实体前。可能的值是:

   Assembly,
   Module,
   Class,
   Struct,
   Enum,
   Constructor,
   Method,
   Property,
   Field,
   Event,
   Interface,
   Parameter,
   Delegate,
   All = Assembly   Module   Class   Struct   Enum   Constructor   Method   Property   Field   Event   Interface   Parameter   Delegate,
   ClassMembers = Class   Struct   Enum   Constructor   Method   Property   Field   Event   Delegate   Interface )

下面考虑一下AllowMultiple = false。它规定了特性不能被重复放置多次。  

  1. [Help("this is a do-nothing class")]
  2.   [Help("it contains a do-nothing method")]
  3.   public class AnyClass
  4.   {
  5.   [Help("this is a do-nothing method")] //error
  6.   public void AnyMethod()
  7.   {
  8.   }
  9.   }
  10.   它产生了一个编译期错误。 
  11.   AnyClass.cs: Duplicate 'Help' attribute 

[Help("this is a do-nothing class")]
   [Help("it contains a do-nothing method")]
   public class AnyClass
   {
   [Help("this is a do-nothing method")] //error
   public void AnyMethod()
   {
   }
   }

   它产生了一个编译期错误。 

   AnyClass.cs: Duplicate 'Help' attribute 

Ok,现在我们来讨论一下最后的这个属性。Inherited, 表明当特性被放置在一个基类上时,它能否被派生类所继承。  

  1. [Help("BaseClass")]
  2. public class Base
  3. {
  4. }
  5. public class Derive : Base
  6. {
  7. }
  8. 这里会有四种可能的组合: 
  9. [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false ]
  10. [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false ]
  11. [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true ]
  12. [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true ]

   [Help("BaseClass")]
   public class Base
   {
   }

   public class Derive : Base
   {
   }

   这里会有四种可能的组合: 

   [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false ]
   [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false ]
   [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true ]
   [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true ]

     第一种情况:  

   如果我们查询(Query)(稍后我们会看到如何在运行期查询一个类的特性)Derive类,我们将会发现Help特性并不存在,因为inherited属性被设置为false。   

   第二种情况:  

   和第一种情况相同,因为inherited也被设置为false。  

   第三种情况:  

   为了解释第三种和第四种情况,我们先来给派生类添加点代码:  

   [Help("BaseClass")]
   public class Base
   {
   }
   [Help("DeriveClass")]
   public class Derive : Base
   {
   }

   现在我们来查询一下Help特性,我们只能得到派生类的属性,因为inherited被设置为true,但是AllowMultiple却被设置为false。因此基类的Help特性被派生类Help特性覆盖了。  

   第四种情况: 

   在这里,我们将会发现派生类既有基类的Help特性,也有自己的Help特性,因为AllowMultiple被设置为true。

C#特性学习笔记一的更多相关文章

  1. java8 新特性学习笔记

    Java8新特性 学习笔记 1主要内容 Lambda 表达式 函数式接口 方法引用与构造器引用 Stream API 接口中的默认方法与静态方法 新时间日期 API 其他新特性 2 简洁 速度更快 修 ...

  2. C#特性学习笔记二

    实例探讨: 自定义了一个特性类: [AttributeUsage(AttributeTargets.Class|AttributeTargets.Method)] class WahAttribute ...

  3. InnoDB关键特性学习笔记

    插入缓存 Insert Buffer Insert Buffer是InnoDB存储引擎关键特性中最令人激动与兴奋的一个功能.不过这个名字可能会让人认为插入缓冲是缓冲池中的一个组成部分.其实不然,Inn ...

  4. C# 特性学习笔记

    1.自己定义的特性 注意注释!!!!! 2.使用特性 3.特性的用处

  5. Python高级特性学习笔记

    切片(slice) 可简化循环取元素的操作. L[0:3] or L[:3] 表示从索引0的位置开始,到索引3为止,但不包括索引3的前3个元素(L[0],L[1],L[2]); L[-2:]表示取包括 ...

  6. java8新特性学习笔记链接

    https://blog.csdn.net/yitian_66/article/details/81010434

  7. html5新特性学习笔记

    1.语义化标签兼容问题(语义化标签只支持ie8以上,不包括ie8) 解决方法一:该标签的css中加上display:block; 通过DOM的方式创建这个标签 document.createEleme ...

  8. Java8新特性学习笔记(一) Lambda表达式

    没有用Lambda表达式的写法: Comparator<Transaction> byYear = new Comparator<Transaction>() { @Overr ...

  9. Go类型特性-学习笔记

    1.组合 Go语言使用组合来完成类型的设计,设计某一类型时想要拥有其他类型的功能只需要将其他类型嵌入该类型即可. 2.接口 与其他语言不同的是,编译器会自动判断该类型是否符合某正在使用的接口,甚至不需 ...

随机推荐

  1. CBUUID UUIDString unrecognized selector sent to instance 错误

    CBUUID UUIDString unrecognized selector sent to instance 错误 ios7.0,4s 蓝牙出现上述错误! 查看api可知,错误原因,由于CBUUI ...

  2. SPSS数据分析—相关分析

    相关系数是衡量变量之间相关程度的度量,也是很多分析的中的当中环节,SPSS做相关分析比较简单,主要是区别如何使用这些相关系数,如果不想定量的分析相关性的话,直接观察散点图也可以. 相关系数有一些需要注 ...

  3. hdu----1686 Oulipo (ac自动机)

    Oulipo Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  4. Android 系统ID介绍

    Android上系统ID有很多,本文只介绍常用的ANDROID ID.DEVICE ID.IMEI/MEID.WIFI/BT ADDRESS等几个,本文介绍这些ID的数据格式.长度及一些基本知识. 一 ...

  5. Servlet实现文件,图片等的下载 含代码

    实现文件的下载源代码如下: package com.fxl.servlet; import java.io.FileInputStream;import java.io.IOException;imp ...

  6. SVN - 忽略已经提交的文件

    1.在本地删除要忽略的文件 2.与资源库同步,提交删除的文件 3.忽略文件

  7. bootstrap学习<三>打开模态窗体

    可以切换模态框(Modal)插件的隐藏内容: 通过 data 属性:在控制器元素(比如按钮或者链接)上设置属性 data-toggle="modal",同时设置 data-targ ...

  8. autotools工具使用记录

    参考 http://blog.chinaunix.net/uid-25100840-id-271131.html http://blog.sina.com.cn/s/blog_4c2bf01a0101 ...

  9. Ubuntu操作系统安装使用教程 (转)

    随着微软的步步紧逼,包括早先的Windows黑屏计划.实施,逮捕番茄花园作者并判刑,种种迹象表明,中国用户免费使用盗版Windows的日子将不会太长久了,那么这个世界上有没有即免费又易用的操作系统呢? ...

  10. 《Java中的单例模式--两种》

    //单例模式:饿汉式和懒汉式 //单例模式 /* 设计模式:解决某一类问题行之有效的解决办法(思想). 单例(Singleton):设计模式: 学习设计模式必须先弄清楚它是解决什么问题的. 单例模式是 ...