顔秌 發表於 2019-12-12 10:59:00

C# 特性(Attribute)

<h2><span style="font-family: 幼圆">Attribute是什么</span></h2>
<p><strong style="font-size: 14px"><span style="font-family: 幼圆; font-size: 15px">Attribute是一种可由用户自有定义的修饰符(Modifier),可以用来修饰各种需要被修饰的目标。我们可以对类、以及C#程序集中的成员进行进一步的描述。</span></strong></p>
<p><span style="font-family: 幼圆; font-size: 15px">简单地说,Attribute就是一种“附着物”——就像牡蛎吸附在船底或礁石上一样。&nbsp;这些附着物的作用是为它们的附着体追加上一些额外的信息(这些信息保存在附着物的体内)——比如“这个类是我写的”或者“这个函数以前出过问题”等等</span></p>
<h2 id="三attribute与注释的区别"><span style="font-family: 幼圆">Attribute与注释的区别</span></h2>
<p><span style="font-family: 幼圆; font-size: 15px">注释是对程序源代码的一种说明,主要目的是给人看的,在程序被编译的时候会被编译器所丢弃,因此,它丝毫不会影响到程序的执行。</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">Attribute是程序代码的一部分,它不但不会被编译器丢弃,而且还会被编译器编译进程序集(Assembly)的元数据(Metadata)里。在程序运行的时候,随时可以从元数据(元数据:.NET中元数据是指程序集中的命名空间、类、方法、属性等信息,这些信息是可以通过Reflection读取出来的。)中提取提取出这些附加信息,并以之决策程序的运行。</span></p>
<h2><span style="font-family: 幼圆">示例</span></h2>
<p><span style="font-family: 幼圆; font-size: 15px">比如我们写一个关于人的类Person,该类可以对人的属性以及某些行为(方法)进行描述。那么如果我们要对人类进行进一步描述呢?比如人这个类是属于动物的灵长类动物,有人会说我们可以为这个Person类去写一个灵长动物类的父类,再用</span><span style="font-family: 幼圆; font-size: 15px">人类去继承这个类去解决。但是我们要求的是仅仅是描述性的,就是对这个人类进行进一步的描述,而在实际操作中不需要去操作。这样的情况我们就可以用特性的概念去解决,<strong>特性简而言之就是程序集的特定程序元素所具有的另外的性质。</strong></span></p>
<div class="cnblogs_code"><span style="font-family: 幼圆; font-size: 15px"><img id="code_img_closed_59620274-7b97-4e0b-8de5-f501925b190c" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_59620274-7b97-4e0b-8de5-f501925b190c" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt=""></span>
<div id="cnblogs_code_open_59620274-7b97-4e0b-8de5-f501925b190c" class="cnblogs_code_hide">
<pre><span style="font-family: 幼圆; font-size: 15px"><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">先定义一个人类Person类</span>
      <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person
      {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">人的姓名储存字段和属性 </span>
            <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> name;
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> Name
            {
                </span><span style="color: rgba(0, 0, 255, 1)">set</span> { name =<span style="color: rgba(0, 0, 0, 1)"> value; }
                </span><span style="color: rgba(0, 0, 255, 1)">get</span> { <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> name; }
            }

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">人的年龄储存字段和属性 </span>
            <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age;
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> Age
            {
                </span><span style="color: rgba(0, 0, 255, 1)">set</span> { age =<span style="color: rgba(0, 0, 0, 1)"> value; }
                </span><span style="color: rgba(0, 0, 255, 1)">get</span> { <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> age; }
            }

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">人的性别储存字段和属性 </span>
            <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">char</span><span style="color: rgba(0, 0, 0, 1)"> sex;
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">char</span><span style="color: rgba(0, 0, 0, 1)"> Sex
            {
                </span><span style="color: rgba(0, 0, 255, 1)">set</span> { sex =<span style="color: rgba(0, 0, 0, 1)"> value; }
                </span><span style="color: rgba(0, 0, 255, 1)">get</span> { <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> sex; }
            }

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">人的打招呼方法 </span>
            <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> SayHello()
            {
                Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">大家好,我叫{this.Name},我今年{this.Age}岁了,我的性别是{this.Sex}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            }
      }

      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">定义动物的特性类AnimalAttribute类继承于Attribute(特性)</span>
      <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> AnimalAttribute : Attribute
      {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">字段和属性描述是否是灵长类</span>
            <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">bool</span><span style="color: rgba(0, 0, 0, 1)"> isPrimate;
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">bool</span><span style="color: rgba(0, 0, 0, 1)"> IsPrimate
            {
                </span><span style="color: rgba(0, 0, 255, 1)">set</span> { isPrimate =<span style="color: rgba(0, 0, 0, 1)"> value; }
                </span><span style="color: rgba(0, 0, 255, 1)">get</span> { <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> isPrimate; }
            }
      }</span></span></pre>
</div>
<span class="cnblogs_code_collapse" style="font-family: 幼圆; font-size: 15px">View Code</span></div>
<p><span style="font-family: 幼圆; font-size: 15px">对人类进行动物类描述。即在人类的定义前面加:</span></p>
<p><strong><span style="font-family: 幼圆; font-size: 15px">   //为人类加特性,指定人类是灵长类。</span></strong></p>
<p><span style="font-family: 幼圆; font-size: 15px"><img src="https://img2018.cnblogs.com/i-beta/1146926/201912/1146926-20191212105041977-1042169615.png" alt=""></span></p>
<p><span style="font-family: 幼圆; font-size: 15px">&nbsp;下面我们就可以通过代码来获得人类的特性:</span></p>
<div class="cnblogs_code"><span style="font-family: 幼圆; font-size: 15px"><img id="code_img_closed_6da245bd-1fba-4344-bbed-b72f197168a5" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_6da245bd-1fba-4344-bbed-b72f197168a5" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt=""></span>
<div id="cnblogs_code_open_6da245bd-1fba-4344-bbed-b72f197168a5" class="cnblogs_code_hide">
<pre><span style="font-family: 幼圆; font-size: 15px"><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">声明特性对象,并通过Attribute类的静态方法GetCustomAttribute()获得人类的在动物类的特性,并赋值给特性对象 </span>
            Attribute att1 = Attribute.GetCustomAttribute(<span style="color: rgba(0, 0, 255, 1)">typeof</span>(Person), <span style="color: rgba(0, 0, 255, 1)">typeof</span><span style="color: rgba(0, 0, 0, 1)">(AnimalAttribute));

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">将特性对象转化为动物特性对象</span>
            AnimalAttribute animalAtt = att1 <span style="color: rgba(0, 0, 255, 1)">as</span><span style="color: rgba(0, 0, 0, 1)"> AnimalAttribute;

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">检查转化是否成功如果成功则打印这个特性对象的是否是灵长类的属性。</span>
            <span style="color: rgba(0, 0, 255, 1)">if</span> (animalAtt != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
            {
                Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">人类是否是灵长类:{0}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, animalAtt.IsPrimate);
            }
            Console.ReadKey(); </span></span></pre>
</div>
<span class="cnblogs_code_collapse" style="font-family: 幼圆; font-size: 15px">View Code</span></div>
<p><span style="font-size: 15px"><strong><span style="font-family: 幼圆; color: rgba(255, 0, 0, 1)">注意:如果一个类有的某个特性类描述多次,则要用GetCustomAt</span><span style="font-family: 幼圆; color: rgba(255, 0, 0, 1)">tributes()方法。</span></strong></span></p>
<h2><span style="font-family: 幼圆"><span style="font-family: 幼圆">Attribute的使用方法:(四种方式完全等价)</span></span></h2>
<div class="cnblogs_code">
<pre><span style="font-family: 幼圆; font-size: 15px"><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">长记法</span>


</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Func()
{Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Created by Li, NoBug</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">); }
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">短记法</span>


</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Func()
{Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Created by Li, NoBug</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">); }
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">换序</span>


</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Func()
{Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Created by Li, NoBug</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">); }
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">单括号叠加</span>

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Func()
{Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Created by Li, NoBug</span><span style="color: rgba(128, 0, 0, 1)">"</span>); } </span></pre>
</div>
<h2><span style="font-family: 幼圆">预定义的特性</span></h2>
<p><strong><span style="font-family: 幼圆; font-size: 15px">obsolete类用来指定该类的成员已经过时,在程序使用这个成员的时候会给出提示。</span></strong></p>
<p><strong><span style="font-family: 幼圆; font-size: 15px">obsolete类有</span><span style="font-family: 幼圆; font-size: 15px">三种重载</span></strong></p>
<p><span style="font-family: 幼圆; font-size: 15px">  public ObsoleteAttribute()</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">  public ObsoleteAttribute(string message)  参数说明: message:描述了可选的变通方法文本字符串。</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">  public ObsoleteAttribute(string message, bool error)  参数说明:message:描述了可选的变通方法文本字符串。  error:true 如果使用过时的元素将生成编译器错误;false 如果使用它将生成编译器警告。</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">比如如果我们的Person类的SayHello()方法现在不能用了,不允许程序员使用这个方法,那么我们就可以在Person类的SayHello方法前面加<strong></strong></span></p>
<p><span style="font-family: 幼圆; font-size: 15px">这样当我们在主程序中用到Person类的SayHello方法的时候程序就会报错。当然,如果第二个参数设置为false时,在调用该成员的时候不会报错,但是会报出警告。</span></p>
<p><span style="font-family: 幼圆; font-size: 15px"><img src="https://img2018.cnblogs.com/i-beta/1146926/201912/1146926-20191212105438058-992578534.png" alt=""></span></p>
<p><span style="font-family: 幼圆; font-size: 15px"><img src="https://img2018.cnblogs.com/i-beta/1146926/201912/1146926-20191212105545927-665763264.png" alt=""></span></p>
<h2><span style="font-family: 幼圆">Attribute作为编译器的指令</span></h2>
<p><span style="font-family: 幼圆; font-size: 15px">在C#中存在着一定数量的编译器指令,如:#define DEBUG, #undefine DEBUG, #if等。这些指令专属于C#,而且在数量上是固定的。而Attribute用作编译器指令则不受数量限制。比如下面的三个Attribute:</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">&nbsp;&nbsp; <strong>Conditional</strong>:起条件编译的作用,只有满足条件,才允许编译器对它的代码进行编译。一般在程序调试的时候使用。&nbsp;</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">&nbsp;&nbsp; <strong>DllImport</strong>:用来标记非.NET的函数,表明该方法在一个外部的DLL中定义。&nbsp;</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">&nbsp;&nbsp; <strong>Obsolete</strong>:这个属性用来标记当前的方法已经被废弃,不再使用了。</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">下面的代码演示了上述三个属性的使用:</span></p>
<div class="cnblogs_code">
<pre><span style="font-family: 幼圆; font-size: 15px"><span style="color: rgba(0, 0, 255, 1)">#define</span> debug   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">定义条件</span>
<span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Diagnostics;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Runtime.InteropServices;

</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> ConsoleApp1
{
    </span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
    {
      
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">int</span> MessageBox(<span style="color: rgba(0, 0, 255, 1)">int</span> hParent, <span style="color: rgba(0, 0, 255, 1)">string</span> Message, <span style="color: rgba(0, 0, 255, 1)">string</span> Caption, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> Type);

      
      </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> DisplayRunningMessage()
      {
            Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">开始运行Main子程序。当前时间是{DateTime.Now}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      }

      
      
      </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> DisplayDebugMessage()
      {
            Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">开始Main子程序</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      }

      </span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
      {
            DisplayRunningMessage();
            DisplayDebugMessage();
            MessageBox(</span><span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Hello</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Message</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">);
            Console.ReadKey();
      }
    }
}</span></span></pre>
</div>
<p><strong><span style="font-family: 幼圆; font-size: 15px">运行结果:</span></strong></p>
<p><span style="font-family: 幼圆; font-size: 15px"><img src="https://img2018.cnblogs.com/i-beta/1146926/201912/1146926-20191212150505449-353019440.png" alt=""></span></p>
<p><strong><span style="font-family: 幼圆; font-size: 15px">解析:</span></strong></p>
<p><span style="font-family: 幼圆; font-size: 15px">如果在一个程序元素前面声明一个Attribute,那么就表示这个Attribute被施加到该元素上。</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">上面的代码,施加到MessageBox函数上, 施加到DisplayRuntimeMessage方法和DisplayDebugMessage方法,施加到</span><span style="font-family: 幼圆; font-size: 15px">DisplayDebugMessage方法上。DllImport Attribute表明了MessageBox是User32.DLL中的</span><span style="font-family: 幼圆; font-size: 15px">函数,这样我们就可以像内部方法一样调用这个函数。</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">重要的一点就是Attribute就是一个类,所以DllImport也是一个类,Attribute类是在编译的时候被实例化的,而不是像通常的类那样在运行时候才实例化。Attribute实例化的时候根据该Attribute类的设计可以带参数,也可以不带参数,比</span><span style="font-family: 幼圆; font-size: 15px">如DllImport就带</span><span style="font-family: 幼圆; font-size: 15px">有"User32.dll"的参数。Conditional对满足参数的定义条件的代码进行编译,如果没有定义debug,那么该方法将不被编译。Obsolete表明了DispalyDebugMessage方法已经过时了,它有一个更好的方法来代替它,当我们的程</span><span style="font-family: 幼圆; font-size: 15px">序调用一个声明了Obsolete的方法</span><span style="font-family: 幼圆; font-size: 15px">时,那么编译器会给出信息。</span></p>
<h2><span style="font-family: 幼圆">Attribute类</span></h2>
<p><span style="font-family: 幼圆; font-size: 15px">除了.NET提供的那些Attribute派生类之外,我们可以自定义我们自己的Attribute,所有自定义的Attribute必须从Attribute类派生。现在我们来看一下Attribute 类的细节:</span></p>
<p><span style="font-family: 幼圆; font-size: 15px"><strong>protected Attribute()</strong>: 保护的构造器,只能被Attribute的派生类调用。</span></p>
<h3><span style="font-family: 幼圆">三个静态方法:</span></h3>
<p><span style="font-family: 幼圆; font-size: 15px"><strong>static Attribute GetCustomAttribute()</strong>:这个方法有8种重载的版本,它被用来取出施加在类成员上指定类型的Attribute。</span></p>
<p><span style="font-family: 幼圆; font-size: 15px"><strong>static Attribute[] GetCustomAttributes()</strong>:这个方法有16种重载版本,用来取出施加在类成员上指定类型的Attribute数组。</span></p>
<p><span style="font-family: 幼圆; font-size: 15px"><strong>static bool IsDefined()</strong>:由八种重载版本,看是否指定类型的定制attribute被施加到类的成员上面。</span></p>
<h3><span style="font-family: 幼圆">实例方法:</span></h3>
<p><span style="font-family: 幼圆; font-size: 15px"><strong>bool IsDefaultAttribute()</strong>:如果Attribute的值是默认的值,那么返回true。</span></p>
<p><span style="font-family: 幼圆; font-size: 15px"><strong>bool Match()</strong>:表明这个Attribute实例是否等于一个指定的对象。</span></p>
<h3><span style="font-family: 幼圆">公共属性:&nbsp;</span></h3>
<p><span style="font-family: 幼圆; font-size: 15px"><strong>TypeId</strong>: 得到一个唯一的标识,这个标识被用来区分同一个Attribute的不同实例。</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">下面介绍如何自定义一个Attribute: </span></p>
<p><span style="font-family: 幼圆; font-size: 15px">自定义一个Attribute并不需要特别的知识,其实就和编写一个类差不多。自定义的Attribute必须直接或者间接地从Attribute这个类派生,如:</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">public MyCustomAttribute : Attribute { ... }</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">这里需要指出的是Attribute的命名规范,也就是你的Attribute的类名+"Attribute",当你的Attribute施加到一个程序的元素上的时候,编译器先查找你的Attribute的定义,如果没有找到,那么它就会查找“Attribute名称"+Attribute的定</span><span style="font-family: 幼圆; font-size: 15px">义。如果都没有找到,那么编译器</span><span style="font-family: 幼圆; font-size: 15px">就报错。</span></p>
<h2><span style="font-family: 幼圆">自定义或控制特性的使用</span></h2>
<p><span style="font-family: 幼圆; font-size: 15px">对于一个自定义的Attribute,可以通过AttributeUsage的Attribute来限定你的Attribute所施加的元素的类型。代码形式如下:</span></p>
<p><span style="font-family: 幼圆; font-size: 15px; color: rgba(255, 0, 0, 1)"><strong> public 自定义Attribute : Attribute { ... }</strong></span></p>
<p><span style="font-family: 幼圆; font-size: 15px">AttributeUsage本身也是一个Attribute,这是专门施加在Attribute类的Attribute. AttributeUsage自然也是从Attribute派生,它有一个带参数的构造器,这个参数是AttributeTargets的枚举类型。下面是AttributeTargets 的定义:</span></p>
<div class="cnblogs_code"><span style="font-family: 幼圆; font-size: 15px"><img id="code_img_closed_c71a8835-0074-45eb-b263-39ea3fb4d6d3" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_c71a8835-0074-45eb-b263-39ea3fb4d6d3" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt=""></span>
<div id="cnblogs_code_open_c71a8835-0074-45eb-b263-39ea3fb4d6d3" class="cnblogs_code_hide">
<pre><span style="font-family: 幼圆; font-size: 15px"><span style="color: rgba(0, 128, 0, 1)">//</span>
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 摘要:
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   指定可应用属性的应用程序元素。</span>
   
   
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> AttributeTargets
    {
      </span><span style="color: rgba(0, 128, 0, 1)">//</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 摘要:
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   特性可以应用于程序集。</span>
      Assembly = <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(0, 128, 0, 1)">//</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 摘要:
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   特性可以应用于模块中。</span>
      Module = <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(0, 128, 0, 1)">//</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 摘要:
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   特性可以应用于类。</span>
      Class = <span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(0, 128, 0, 1)">//</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 摘要:
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   特性可以应用于结构;即,类型值。</span>
      Struct = <span style="color: rgba(128, 0, 128, 1)">8</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(0, 128, 0, 1)">//</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 摘要:
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   特性可以应用于枚举。</span>
      Enum = <span style="color: rgba(128, 0, 128, 1)">16</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(0, 128, 0, 1)">//</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 摘要:
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   特性可以应用于构造函数。</span>
      Constructor = <span style="color: rgba(128, 0, 128, 1)">32</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(0, 128, 0, 1)">//</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 摘要:
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   特性可以应用于方法。</span>
      Method = <span style="color: rgba(128, 0, 128, 1)">64</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(0, 128, 0, 1)">//</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 摘要:
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   特性可以应用于属性。</span>
      Property = <span style="color: rgba(128, 0, 128, 1)">128</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(0, 128, 0, 1)">//</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 摘要:
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   特性可以应用于字段。</span>
      Field = <span style="color: rgba(128, 0, 128, 1)">256</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(0, 128, 0, 1)">//</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 摘要:
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   特性可以应用于事件。</span>
      Event = <span style="color: rgba(128, 0, 128, 1)">512</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(0, 128, 0, 1)">//</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 摘要:
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   特性可以应用于接口。</span>
      Interface = <span style="color: rgba(128, 0, 128, 1)">1024</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(0, 128, 0, 1)">//</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 摘要:
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   特性可以应用于参数。</span>
      Parameter = <span style="color: rgba(128, 0, 128, 1)">2048</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(0, 128, 0, 1)">//</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 摘要:
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   特性可以应用于委托。</span>
      Delegate = <span style="color: rgba(128, 0, 128, 1)">4096</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(0, 128, 0, 1)">//</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 摘要:
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   特性可以应用于返回的值。</span>
      ReturnValue = <span style="color: rgba(128, 0, 128, 1)">8192</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(0, 128, 0, 1)">//</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 摘要:
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   特性可以应用于泛型参数。</span>
      GenericParameter = <span style="color: rgba(128, 0, 128, 1)">16384</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(0, 128, 0, 1)">//</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 摘要:
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   特性可以应用于任何应用程序元素。</span>
      All = <span style="color: rgba(128, 0, 128, 1)">32767</span><span style="color: rgba(0, 0, 0, 1)">
    }</span></span></pre>
</div>
<span class="cnblogs_code_collapse" style="font-family: 幼圆; font-size: 15px">View Code</span></div>
<p><span style="font-family: 幼圆; font-size: 15px">作为参数的AttributeTarges的值允许通过“或”操作来进行多个值得组合,如果你没有指定参数,那么默认参数就是All 。</span></p>
<div class="cnblogs_code">
<pre><span style="font-family: 幼圆; font-size: 15px"></span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 15px">AttributeUsage除了继承Attribute 的方法和属性之外,还定义了以下三个属性:</span></p>
<p><span style="font-family: 幼圆; font-size: 15px"><strong>AllowMultiple</strong>:读取或者设置这个属性,表示是否可以对一个程序元素施加多个Attribute 。</span></p>
<p><span style="font-family: 幼圆; font-size: 15px"><strong>Inherited</strong>:读取或者设置这个属性,表示是否施加的Attribute 可以被派生类继承或者重载。</span></p>
<p><span style="font-family: 幼圆; font-size: 15px"><strong>ValidOn</strong>: 读取或者设置这个属性,指明Attribute 可以被施加的元素的类型。</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">示例:在Help特性前放置AttributeUsage特性以期待在它的帮助下控制Help特性的使用</span></p>
<div class="cnblogs_code">
<pre><span style="font-family: 幼圆; font-size: 15px">
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> HelpAttribute : Attribute
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> HelpAttribute(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> Description_in)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.description =<span style="color: rgba(0, 0, 0, 1)"> Description_in;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> description;
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> Description
    {
      </span><span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)">
      {
            </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.description;
      }
    }
}</span></span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 15px">AttributeTargets.Class 它规定了Help特性只能被放在class的前面。这也就意味着下面的代码将会产生错误:</span></p>
<p><span style="font-family: 幼圆; font-size: 15px"><img src="https://img2018.cnblogs.com/i-beta/1146926/201912/1146926-20191212151538224-261804547.png" alt=""></span></p>
<p><span style="font-family: 幼圆; font-size: 15px">我们可以使用AttributeTargets.All来允许Help特性被放置在任何程序实体前。可能的值是:</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">Assembly,Module,Class,Struct,Enum,Constructor,Method,Property,Field,Event,Interface,<em id="__mceDel">Parameter,Delegate。</em></span></p>
<p><span style="font-family: 幼圆; font-size: 15px">All&nbsp;= Assembly | Module | Class | Struct | Enum | Constructor | Method | Property | Field | Event | Interface | Parameter | Delegate,</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">ClassMembers&nbsp;= Class | Struct | Enum | Constructor | Method | Property | Field | Event | Delegate | Interface )</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">下面考虑一下AllowMultiple = false。它规定了特性不能被重复放置多次</span></p>
<p><span style="font-family: 幼圆; font-size: 15px"><img src="https://img2018.cnblogs.com/i-beta/1146926/201912/1146926-20191212151928308-1979648390.png" alt=""></span></p>
<p><span style="font-family: 幼圆; font-size: 15px">&nbsp;</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-family: 幼圆; font-size: 15px">原文链接:https://blog.csdn.net/qq_38507850/article/details/79181319</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">原文链接:https://blog.csdn.net/xiaouncle/article/details/70216951</span></p>
<p><span style="font-family: 幼圆"><span style="font-size: 15px">原文链接:https://www.cnblogs.com/wangluochong/p/3733897.html</span></span></p><br><br>
来源:https://www.cnblogs.com/zhaoyl9/p/12027938.html
頁: [1]
查看完整版本: C# 特性(Attribute)