C#中的特性与反射

一、特性

特性是一个类,用来标记在某个元素上增加一定行为信息的声明性标签。一个声明性标签是通过放置在它所应用的元素前面的方括号[]来描述的。

预定义特性

Conditional:这个预定义特性标记了一个条件方法,用于在条件编译,如[Conditiaol("Debug")]

Obsolete:这个预定义特性标记了不应再使用的程序实体。如果iserror为true时,编译器将会生成一个错误,必须调用新的方法来替代

AttributeUsage这个预定义特性描述如何使用一个自定义特性类,如果有自定义特性类时,需要配合它实现相应的功能。

 

如何自定义特性

1、定义一个类,直接或间接继承于Attribute

2、约定俗成的以Attribute为后缀,但是这个是可选的

3、以Attribute结尾(为后缀的)的,使用的时候可以省略Attribute

4、标记-修饰:类及类内部的所有元素

5、默认不能重复标记,如果需要重复标记,需要设置AllowMultiple=true,默认是不被继承的,如果需要则设置inherited=true

 

特性的功能是通过反射来实现的

 

using System;
using System.Reflection;
namespace BugFixApplication
{
   // 一个自定义特性 BugFix 被赋给类及其成员
   [AttributeUsage(AttributeTargets.Class |
   AttributeTargets.Constructor |
   AttributeTargets.Field |
   AttributeTargets.Method |
   AttributeTargets.Property,
   AllowMultiple = true)]

   public class DeBugInfo : System.Attribute
   {
      private int bugNo;
      private string developer;
      private string lastReview;
      public string message;

      public DeBugInfo(int bg, string dev, string d)
      {
         this.bugNo = bg;
         this.developer = dev;
         this.lastReview = d;
      }

      public int BugNo
      {
         get
         {
            return bugNo;
         }
      }
      public string Developer
      {
         get
         {
            return developer;
         }
      }
      public string LastReview
      {
         get
         {
            return lastReview;
         }
      }
      public string Message
      {
         get
         {
            return message;
         }
         set
         {
            message = value;
         }
      }
   }
   [DeBugInfo(45, "Zara Ali", "12/8/2012",
        Message = "Return type mismatch")]
   [DeBugInfo(49, "Nuha Ali", "10/10/2012",
        Message = "Unused variable")]
   class Rectangle
   {
      // 成员变量
      protected double length;
      protected double width;
      public Rectangle(double l, double w)
      {
         length = l;
         width = w;
      }
      [DeBugInfo(55, "Zara Ali", "19/10/2012",
           Message = "Return type mismatch")]
      public double GetArea()
      {
         return length * width;
      }
      [DeBugInfo(56, "Zara Ali", "19/10/2012")]
      public void Display()
      {
         Console.WriteLine("Length: {0}", length);
         Console.WriteLine("Width: {0}", width);
         Console.WriteLine("Area: {0}", GetArea());
      }
   }//end class Rectangle  
   
   class ExecuteRectangle
   {
      static void Main(string[] args)
      {
         Rectangle r = new Rectangle(4.5, 7.5);
         r.Display();
         Type type = typeof(Rectangle);
         // 遍历 Rectangle 类的特性
         foreach (Object attributes in type.GetCustomAttributes(false))
         {
            DeBugInfo dbi = (DeBugInfo)attributes;
            if (null != dbi)
            {
               Console.WriteLine("Bug no: {0}", dbi.BugNo);
               Console.WriteLine("Developer: {0}", dbi.Developer);
               Console.WriteLine("Last Reviewed: {0}",
                                        dbi.LastReview);
               Console.WriteLine("Remarks: {0}", dbi.Message);
            }
         }
         
         // 遍历方法特性
         foreach (MethodInfo m in type.GetMethods())
         {
            foreach (Attribute a in m.GetCustomAttributes(true))
            {
               DeBugInfo dbi = (DeBugInfo)a;
               if (null != dbi)
               {
                  Console.WriteLine("Bug no: {0}, for Method: {1}",
                                                dbi.BugNo, m.Name);
                  Console.WriteLine("Developer: {0}", dbi.Developer);
                  Console.WriteLine("Last Reviewed: {0}",
                                                dbi.LastReview);
                  Console.WriteLine("Remarks: {0}", dbi.Message);
               }
            }
         }
         Console.ReadLine();
      }
   }
}

注意:上面在调用DeBugInfo dbi = (DeBugInfo)a;时会报错

System.InvalidCastException:“Unable to cast object of type 'System.Runtime.CompilerServices.NullableContextAttribute' to type 'testAttribute.DebugInfo'.”

需要修改为    foreach(MethodInfo info in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public))

因为默认调用的类中含有GetType(),GetHashCode(),ToString()及Equals()等方法

 

posted @ 2022-12-05 15:07  unicornsir  阅读(127)  评论(0编辑  收藏  举报