属性和元数据

数据

C#和C++之间一个显著的区别是它提供了对元数据的支持:有关类、对象、方法等其他实体的数据。属性可以分为二类:一类以CLR的一部分的形式出现,另一种是我们自己创建的属性,CLR属性用来支持串行化、排列和COM协同性等。一些属性是针对一个组合体的,有些属性则是针对类或界面,它们也被称作是属性目标。

将属性放在属性目标前的方括号内,属性就可以作用于它们的属性目标。

[assembly:AssemblyDelaySign(false)]
[assembly:AssemblyKeyFile(".\\keyFile.snk")]

或用逗号将各个属性分开:

[assembly:AssemblyDelaySign(false),
assembly:AssemblyKeyFile(".\\keyFile.snk")]

自定义的属性

我们可以任意创建自定义属性,并在认为合适的时候使用它们。假设我们需要跟踪bug的修复情况,就需要建立一个包含bug的数据库,但需要将bug报告与专门的修正情况绑定在一块儿,则可能在代码中添加如下所示的注释:

//Bug323fixedbyJesseLiberty1/1/2005.

这样,在源代码中就可以一目了然地了解bug的修正情况,但如果如果把相关的资料保存在数据库中可能会更好,这样就更方便我们的查询工作了。如果所有的bug报告都使用相同的语法那就更好了,但这时我们就需要一个定制的属性了。我们可能使用下面的内容代替代码中的注释:

[BugFix(323,"JesseLiberty","1/1/2005")Comment="Offbyoneerror"]

与C#中的其他元素一样,属性也是类。定制化的属性类需要继承System.Attribute:

publicclassBugFixAttribute:System.Attribute

我们需要让编译器知道这个属性可以跟什么类型的元素,我们可以通过如下的方式来指定该类型的元素:

[AttributeUsage(AttributeTargets.ClassMembers,AllowMultiple=true)]

AttributeUsage是一个作用于属性的属性━━元属性,它提供的是元数据的元数据,也即有关元数据的数据。在这种情况下,我们需要传递二个参数,第一个是目标(在本例中是类成员。),第二个是表示一个给定的元素是否可以接受多于一个属性的标记。AllowMultiple的值被设置为true,意味着类成员可以有多于一个BugFixAttribute属性。如果要联合二个属性目标,可以使用OR操作符连接它们。

[AttributeUsage(AttributeTargets.Class|AttributeTargets.Interface,AllowMultiple=true)]

上面的代码将使一个属性隶属于一个类或一个界面。

新的自定义属性被命名为BugFixAttribute。命名的规则是在属性名之后添加Attribute。在将属性指派给一个元素后,编译器允许我们使用精简的属性名调用这一属性。因此,下面的代码是合法的:

[BugFix(123,"JesseLiberty","01/01/05",Comment="Offbyone")]

编译器将首先查找名字为BugFix的属性,如果没有发现,则查找BugFixAttribute。

每个属性必须至少有一个构造器。属性可以接受二种类型的参数:环境参数和命名参数。在前面的例子中,bugID、编程人员的名字和日期是环境参数,注释是命名参数。环境参数被传递到构造器中的,而且必须按在构造器中定义的顺序传递。

publicBugFixAttribute(intbugID,stringprogrammer,stringdate)
{
this.bugID=bugID;
this.programmer=programmer;
this.date=date;
}

Namedparametersareimplementedasproperties.

属性的使用

为了对属性进行测试,我们创建一个名字为MyMath的简单类,并给它添加二个函数,然后给它指定bugfix属性。

[BugFixAttribute(121,"JesseLiberty","01/03/05")]

[BugFixAttribute(107,"JesseLiberty","01/04/05",
Comment="Fixedoffbyoneerrors")]
publicclassMyMath

这些数据将与元数据存储在一起。下面是完整的源代码及其输出:

自定义属性

usingSystem;
//创建被指派给类成员的自定义属性
[AttributeUsage(AttributeTargets.Class,
AllowMultiple=true)]
publicclassBugFixAttribute:System.Attribute
{
//位置参数的自定义属性构造器
publicBugFixAttribute
(intbugID,
stringprogrammer,
stringdate)
{
this.bugID=bugID;
this.programmer=programmer;
this.date=date;
}
publicintBugID
{
get
{
returnbugID;
}
}

//命名参数的属性
publicstringComment
{
get
{
returncomment;
}
set
{
comment=value;
}
}

publicstringDate
{
get
{
returndate;
}
}

publicstringProgrammer
{
get
{
returnprogrammer;
}
}

//专有成员数据
privateintbugID;
privatestringcomment;
privatestringdate;
privatestringprogrammer;
}

//把属性指派给类

[BugFixAttribute(121,"JesseLiberty","01/03/05")]
[BugFixAttribute(107,"JesseLiberty","01/04/05",
Comment="Fixedoffbyoneerrors")]
publicclassMyMath
{

publicdoubleDoFunc1(doubleparam1)
{
returnparam1+DoFunc2(param1);
}

publicdoubleDoFunc2(doubleparam1)
{
returnparam1/3;
}

}

publicclassTester
{
publicstaticvoidMain()
{
MyMathmm=newMyMath();
Console.WriteLine("CallingDoFunc(7).Result:{0}",
mm.DoFunc1(7));
}
}

输出:

CallingDoFunc(7).Result:9.3333333333333339

象我们看到的那样,属性对输出绝对没有影响,创建属性也不会影响代码的性能。到目前为止,读者也只是在听我论述有关属性的问题,使用ILDASM浏览元数据,就会发现属性确实是存在的。

时间: 2024-10-03 11:39:46

属性和元数据的相关文章

属性和元数据 -- zt

属性和元数据   C#和C++之间一个显著的区别是它提供了对元数据的支持:有关类.对象.方法等其他实体的数据.属性可以分为二类:一类以CLR的一部分的形式出现,另一种是我们自己创建的属性,CLR属性用来支持串行化.排列和COM协同性等.一些属性是针对一个组合体的,有些属性则是针对类或界面,它们也被称作是属性目标.   将属性放在属性目标前的方括号内,属性就可以作用于它们的属性目标.   [assembly:AssemblyDelaySign(false)] [assembly:AssemblyK

ASP.NET 2.0服务器控件开发之复杂属性

asp.net|服务器|控件|控件开发 在上一篇文章中,曾经提及"复杂属性"的概念.复杂属性的最大特征是属性的类型是本身具有属性(称为子属性)的类.通常情况下,复杂属性表现为3种形式:连字符形式属性.内部嵌套形式属性和内部嵌套形式默认属性.本文将介绍以上3种形式复杂属性的具体实现方法. 1. 实现连字符形式复杂属性 连字符形式属性是比较常见的复杂属性.我们常用的Font属性就是一个复杂属性,其包括多个子属性,如Bold.Name等.这种类型属性具有两种语法格式:一种是利用连字符语法,在

《OEA - 实体扩展属性系统 - 设计方案说明书》

 这篇设计文档是 12 月份写来参加公司的研发峰会的,自己倒是信心满满,不过最后还是没有入围.现在想想也没啥大用,所以贴出来,期待与园友交流.     文档有点长,没全部贴在博客中,有兴趣的可以下载附件中的 PDF.  附件:<实体扩展属性系统-系统设计说明书.pdf> ================= 分隔线 ======================     目录 前言... 4 1 背景与需求... 5 1.1 产品 721 客户化开发的需要... 5 1.2 实体动态列... 6

OC 自动生成分类属性方法

分类属性方法自动生成编码全过程. 背景 分类,在 iOS 开发中,是常常需要用到的.在分类里添加属性也是常有的事,但分类中无法添加实例变量,编译器也无法为提供分类中属性的 getter 和 setter 方法了.一般而言,需要手动来实现这两个方法,如果只是用来存储变量的话,关联对象很容易做到这一点: @interface NSObject (db_sqlite) @property (nonatomic, assign) int db_rowid; @end @implementation NS

ASP.NET 2.0服务器控件开发之复杂属性_实用技巧

在上一篇文章中,曾经提及"复杂属性"的概念.复杂属性的最大特征是属性的类型是本身具有属性(称为子属性)的类.通常情况下,复杂属性表现为3种形式:连字符形式属性.内部嵌套形式属性和内部嵌套形式默认属性.本文将介绍以上3种形式复杂属性的具体实现方法. 1. 实现连字符形式复杂属性 连字符形式属性是比较常见的复杂属性.我们常用的Font属性就是一个复杂属性,其包括多个子属性,如Bold.Name等.这种类型属性具有两种语法格式:一种是利用连字符语法,在控件的开始标记中保存子属性,例如,Fon

2000条你应知的WPF小姿势 基础篇&lt;51-56 依赖属性&gt;

原文:2000条你应知的WPF小姿势 基础篇<51-56 依赖属性> 前一阵子由于个人生活原因,具体见上一篇,耽搁了一阵子,在这里也十分感谢大家支持和鼓励.现在开始继续做WPF2000系列. 在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000ThingsYou Should Know About C#  和 2,000 Things You Should Know About WPF .他以类似微博式的150字简短语言

依赖属性之“风云再起”

一. 摘要 首先圣殿骑士很高兴"WPF 基础到企业应用系列" 能得到大家的关注.支持和认可.看到很多朋友留言希望加快速度的问题,我会尽力的,对你们的热情关注也表示由衷的感谢.这段时间更新慢的主要原因是因为忙着用TDD还原MONO的框架,同时也因为一直在研究云计算,所以就拖拖拉拉一直没有发布后面的文章.由于WPF整个系列是自己的一些粗浅心得和微薄经验,所以不会像写书那么面面俱到,如果有不足或者错误之处也请大家见谅.在今年之内圣殿骑士会尽量完成"WPF 基础到企业应用系列&quo

ASP.NET 2.0服务器控件之实现验证控件

asp.net|服务器|控件 为了更好的创建交互式Web应用程序,加强应用程序安全性(例如,防止脚本入侵等),开发人员应该对用户输入的部分提供验证功能.过去,输入验证功能基本由自行编写的客户端脚本来完成这种实现方法既繁琐,又容易出现错误.随着技术的发展,ASP.NET技术通过提供一系列验证控件来克服这些缺点,例如,RequiredFieldValidator.CompareValidator.RangeValidator等.使用这些验证控件,开发人员可以向Web页面添加输入验证功能,例如定义验证

由C++转向C#:我们需要注意哪些方面的变化?

c++ 每隔10年左右,编程人员就需要花费大量的时间和精力去学习新的编程技术.在80年代是Unix和C,90年代是Windows和C++,现在又轮到了微软的.NETFramework和C#.尽管需要学习新的技术,但由此带来的好处却远高于付出的劳动.幸运的是,使用C#和.NET进行的大多数工程的分析和设计与在C++和Windows中没有本质的变化.在本篇文章中,我将介绍如何实现由C++到C#的飞跃. 已经有许多文章介绍过C#对C++的改进,在这里我就不再重复这些问题了.在这里,我将重点讨论由C++