设计模式体现的是一种思想,而思想是指导行为的一切------------开发智能要比机械性的生产商品要简单的多./我要从南走到北,从1到2^10/-----------------Life is a pure flame, and we live by an invisible within us.

13.C# 特性[摘自网络]

上一篇 / 下一篇  2008-05-05 17:38:07 / 个人分类:::名词类::

   http://blog.csdn.net/ojekleen/archive/2007/09/18/1789673.aspx

    特性(Attributes)是一种崭新的声明性信息。我们不仅可以通过特性来定义设计层面的信息(例如help file, URL for documentation)以及运行时(run-time)信息(例如使XML与class相联系),而且我们还可以利用特性建立自描述(self- describing)组件。在这篇教程中,我们将会看到如何建立和添加特性到各种程序实体以及如何在运行时环境中获取特性信息。
k }omc6p0   定义ITPUB个人空间(A/PJ;Lj)Y2{/_
   正如MSDN中所描述的那样-----  
2J~:gA:W)X:?0   “特性是被指定给某一声明的一则附加的声明性信息。”  
\#e7pU1j0  使用预定义(Pre-defined)特性  ITPUB个人空间-h w9yt]$H6`.{P
  在C#中,有一个小的预定义特性集合。在学习如何建立我们自己的定制特性(custom attributes)之前,我们先来看看在我们的代码中如何使用预定义特性。  ITPUB个人空间Y.mc7Kw
  using System;ITPUB个人空间7Q:naj ~M.@
  public class AnyClassITPUB个人空间$d:n9f zq"c nh
  {
3TJ I Lf"p9E\0   [Obsolete("Don't use Old method, use New method", true)]
~+O.fI I'P0   static void Old( ) { }  
v'hQ9p8e'Ts0   static void New( ) { }  ITPUB个人空间y;f l6}P\"e2W
   public static void Main( )ITPUB个人空间NS:J)BL"H r+qM AX\
   {
DcX5^d0   Old( );ITPUB个人空间W"eV5PU.Sm0[j
   }ITPUB个人空间@+} ~Xq_*RV[H6u
  }ITPUB个人空间8^6Zp |9Yh8D/TWZ(U
  我们先来看一下上面这个例子,在这个例子中我们使用了Obsolete特性,它标记了一个不应该再被使用的程序实体。第一个参数是一个字符串,它解释了为什么该实体是过时的以及应该用什么实体来代替它。实际上,你可以在这里写任何文本。第二个参数告诉编译器应该把使用这个过时的程序实体当作 一种错误。它的默认值是false,也就是说编译器对此会产生一个警告。  ITPUB个人空间KFbp.y [r
  当我们尝试编译上面这段程序的时候,我们将会得到一个错误:  ITPUB个人空间Vzl,t6L~kK0[
  AnyClass.Old()' is obsolete: 'Don't use Old method, use New method'    ITPUB个人空间 I}#^7OF'Y
  开发定制特性(custom attributes) ITPUB个人空间%jRO6Sq7sw
  现在让我们来看看如何开发我们自己的特性。 ITPUB个人空间'd&eLf`
  首先我们要从System.Attribute派生出我们自己的特性类(一个从System.Attribute抽象类继承而来的类,不管是直接还是间接继承,都会成为一个特性类。特性类的声明定义了一种可以被放置在声明之上新的特性)。  
Ba*n1pk^0  using System;ITPUB个人空间j0y$i-v*FNP
  public class HelpAttribute : Attribute
` t%S nS{L0  {ITPUB个人空间5C3lH@"]"I U-JS V
  }
/DZ7BWDE"t^0  不管你是否相信,我们已经建立了一个定制特性,现在我们可以用它来装饰现有的类就好像上面我们使用Obsolete attribute一样。  
u7{V!AB.Nq;N9i0  [Help()]
Ig'v],T!Y3S0  public class AnyClassITPUB个人空间:h,DJ$N9E.Ye
  {
]$L]5L$J ] H)m0  }
+^ b2F)[/k4F0  注意:对一个特性类名使用Attribute后缀是一个惯例。然而,当我们把特性添加到一个程序实体,是否包括Attribute后缀是我们 的自由。编译器会首先在System.Attribute的派生类中查找被添加的特性类。如果没有找到,那么编译器会添加Attribute后缀继续查 找。  ITPUB个人空间J'T @"B5e
  到目前为止,这个特性还没有起到什么作用。下面我们来添加些东西给它使它更有用些。  
\!M`3V&_8? ~6lhlA0  using System;ITPUB个人空间'^&uhGqQyX0BG
  public class HelpAttribute : AttributeITPUB个人空间#k2a5?']9Jd Nr
  {ITPUB个人空间/bQ-]5L5Xr
   public HelpAttribute(String Descrition_in)
v9oZCXS0   {
DX(U;j#V(a0   this.description = Description_in;
*[$Q QYd WU#tO0   }ITPUB个人空间+e.A,?~1VY
   protected String description;ITPUB个人空间Ny{O*]@,w&_:Q3W#E
   public String Description
$\5{8glsaaN1Y0   {ITPUB个人空间'^1A W%RxG
   getITPUB个人空间F7t/U6wO5w
   {
B,Y!oJD{[8FG{0   return this.description;  ITPUB个人空间:Zr,Y` y~~Et
   }ITPUB个人空间-qOT,yb
   }
,Jb0A(}N0  }ITPUB个人空间cu ^;c4M
  [Help("this is a do-nothing class")]
y9c9z N'B~~0  public class AnyClassITPUB个人空间8B#b8t+})C?
  {
9fDu(azh F)p0  }
O._C |P'_'C/V0  在上面的例子中,我们给HelpAttribute特性类添加了一个属性并且在后续的部分中我们会在运行时环境中查寻它。ITPUB个人空间J%r&@0O6b9I H
     定义或控制特性的使用  ITPUB个人空间1A[9w;s6r r"b

 AttributeUsage类是另外一个预定义特性类,它帮助我们控制我们自己的定制特性的使用。它描述了一个定制特性如和被使用。  
+ow]3]&oDu3@i0  AttributeUsage
有三个属性,我们可以把它放置在定制属性前面。第一个属性是:  
,\z/CIHYQrEi*H0  ValidOn  
nD a#~/~AT1|M0  
通过这个属性,我们能够定义定制特性应该在何种程序实体前放置。一个属性可以被放置的所有程序实体在AttributeTargets enumerator中列出。通过OR操作我们可以把若干个AttributeTargets值组合起来。  ITPUB个人空间F(O7HD"|$f!u
  AllowMultiple  
0lZ3b%S;oM J0  
这个属性标记了我们的定制特性能否被重复放置在同一个程序实体前多次。 ITPUB个人空间7?N ?JQ&om
  Inherited  ITPUB个人空间:n e U;F1| {@ G
  
我们可以使用这个属性来控制定制特性的继承规则。它标记了我们的特性能否被继承。  
w5|0JP-e y'^*t0  
下面让我们来做一些实际的东西。我们将会在刚才的Help特性前放置AttributeUsage特性以期待在它的帮助下控制Help特性的使用。  
0uZJa8O{ p0  using System;ITPUB个人空间v+F`&O)?7Y\V nC \
  [AttributeUsage(AttributeTargets.Class, AllowMultiple = false,ITPUB个人空间ZB$G"_]'^Fztu
   Inherited = false)
]ITPUB个人空间f2G O6G+rA
  public class HelpAttribute : Attribute
2{/rYphjH!cl0  {ITPUB个人空间&[ V M/M)W!j-M2k y2|
   public HelpAttribute(String Description_in)ITPUB个人空间`*^L$p.L8X*ujB
   {
$YOl.Ro8~9j F/K0   this.description = Description_in;
Ol E;bE8HN0   }ITPUB个人空间&k$c Oq(X(?
   protected String description;ITPUB个人空间U F)D/gCs~7L7W`
   public String Description
-?`+?sg O.IL3[0   {ITPUB个人空间$k7qgIZAP;Wp-m#C
   getITPUB个人空间^/pq eG#sY
   {ITPUB个人空间 O%AS)@3p5~ YFUvUI
   return this.description;
3v"K&Z S7GrD!`&`)W0   }ITPUB个人空间 x1Y8x%x d$k7k&Q"w9b
   }
-O@9Tt%V8k$q0  }
x}9LT;u]4z(d-t1J0  
先让我们来看一下AttributeTargets.Class。它规定了Help特性只能被放在class的前面。这也就意味着下面的代码将会产生错误:
2n(hj8k3GDYCuo0  
d7e*bhY9N t0  [Help("this is a do-nothing class")]ITPUB个人空间Vhxl(u q0X E,Fx
  public class AnyClass
5@4b$V%Ug6Uog0  {
a$G)KE*EEc;O"l P0   [Help("this is a do-nothing method")] //errorITPUB个人空间R:w3C!i+Cs*LA1[
   public void AnyMethod()
?/c/u)J TKe3e0   {
u'_&s }.TM0   }
%f xOCcY5m'\8{0  }ITPUB个人空间Gy"] hp'hY*K-F2x
  
编译器报告错误如下:  ITPUB个人空间&N1R+\/i0bS3wk
  AnyClass.cs: Attribute 'Help' is not valid on this declaration type.  ITPUB个人空间yl l AF W
  It is valid on 'class' declarations only.  
@+h8b.|*M'C9Xx0  
我们可以使用AttributeTargets.All来允许Help特性被放置在任何程序实体前。可能的值是:  ITPUB个人空间)Z/ZS)Ix!Pe
  Assembly,
0l[R2\k0nibo0  Module,
&G0i0WCA7A0  Class,
!abf-d`O0  Struct,ITPUB个人空间$y%i7v7H*r\1Z
  Enum,ITPUB个人空间Mn,?#t5f2^0f,hsW+i
  Constructor,
cLnqx;{0  Method,ITPUB个人空间._g'g6n ?[
  Property,
z0U:T%ft7o0  Field,ITPUB个人空间L0TJS1I\\q
  Event,ITPUB个人空间/M:ac)wIN&\6M7p
  Interface,ITPUB个人空间 T%l,TC!b,I'H
  Parameter,
!v+d/rlUdp0  Delegate,
.Y N^7dl3P"nE}|0  All = Assembly | Module | Class | Struct | Enum | Constructor | Method | Property | Field | Event | Interface | Parameter | Delegate,
;_H8S8g,v}4L\0  ClassMembers = Class | Struct | Enum | Constructor | Method | Property | Field | Event | Delegate | Interface )
c-Gu)}YPX0  
下面考虑一下AllowMultiple = false。它规定了特性不能被重复放置多次。  ITPUB个人空间%WS)m+~3O,j n:C
  [Help("this is a do-nothing class")]ITPUB个人空间5k Q"D"L w(APeUP1X x
  [Help("it contains a do-nothing method")]
U-b.l _:U*A0  public class AnyClass
o6q u YKg0  {
O,nx K&d7z A)S0   [Help("this is a do-nothing method")] //errorITPUB个人空间&wo,A!w}cUI6b
   public void AnyMethod()ITPUB个人空间$f.h} a_ n em&K
   {ITPUB个人空间7XBX-E9X/}_-[
   }ITPUB个人空间y|"I r9Q _!m3M
  }ITPUB个人空间L/qIxOM
  
它产生了一个编译期错误。  
7BS:Vk]o,CS0  AnyClass.cs: Duplicate 'Help' attribute  ITPUB个人空间6f u3`Y2e[i0L
  Ok,
现在我们来讨论一下最后的这个属性。Inherited,表明当特性被放置在一个基类上时,它能否被派生类所继承。  ITPUB个人空间i8NT?X#E.y,B3k
  [Help("BaseClass")]
M \ps7t/D/mmm0  public class BaseITPUB个人空间/y&aBKnKKT
  {ITPUB个人空间8VFrM*q
  }  ITPUB个人空间 m#i fR*I+wDB
  public class Derive : BaseITPUB个人空间9b3H7pi!ZV N
  {
z,`"X5`\}z0  }
*`?]%K+M6P0  
这里会有四种可能的组合:  
Zyk Jl0  [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false ]
EyitV"GH0  [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false ]
3K"B&\Tg(G,S0  [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true ]
-rv7Y*QiR!}kz$r0S0  [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true ]ITPUB个人空间d+E p(nk A1N H5R h
  
第一种情况:  ITPUB个人空间aY3KI(J
  
如果我们查询(Query)(稍后我们会看到如何在运行期查询一个类的特性)Derive类,我们将会发现Help特性并不存在,因为inherited属性被设置为false  
&aiRtga*N4N%x0  
第二种情况:  ITPUB个人空间*P6al]qK4h
  
和第一种情况相同,因为inherited也被设置为false 
Oi#N,h9lK*@t5F4o0  
第三种情况:  
| CY._*x+up|3o0  
为了解释第三种和第四种情况,我们先来给派生类添加点代码:  ITPUB个人空间%YK%INx,|.}.L
  [Help("BaseClass")]ITPUB个人空间?Q X"i3v IX
  public class Base
hvB$Zx{w1kR6D0  {
)D!p$g8|/hy0  }
7^:L,\ \Z8y0  [Help("DeriveClass")]ITPUB个人空间 TU,x$PA$bU3L
  public class Derive : BaseITPUB个人空间bLA4M9eqDc)l"\;If
  {ITPUB个人空间X3O n~Htbo
  }
7Nh"`'b3QPn*[z0  
现在我们来查询一下Help特性,我们只能得到派生类的属性,因为inherited被设置为true,但是AllowMultiple却被设置为false。因此基类的Help特性被派生类Help特性覆盖了。  
3C(LG#c2e0  
第四种情况:  ITPUB个人空间5HO9nAy3@ y8Y7k
  
在这里,我们将会发现派生类既有基类的Help特性,也有自己的Help特性,因为AllowMultiple被设置为true


TAG:

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

日历

« 2008-10-13  
   1234
567891011
12131415161718
19202122232425
262728293031 

数据统计

  • 访问量: 393
  • 日志数: 17
  • 建立时间: 2008-04-10
  • 更新时间: 2008-05-14

RSS订阅

Open Toolbar