特性随笔

MSDN是这样描述的:特性提供功能强大的方法,用以将声明信息与代码(类型、方法、属性等)相关联。属性与程序实体关联后,即可在运行时使用名为“反射”的技术查询属性。

简单的理解,它是程序集,类,方法,属性等的附加信息。

基础概念以及用法,参见msdn

1.特性参数

特性本身就是一个类,直接或间接继承自System.Attribute,它也具有属性,字段,方法,构造函数等。

特性参数,包括定位参数、未命名参数或命名参数。定位参数总出现第一个,实际上就是特性构造函数的参数;命名参数为特性的属性。

2.AttributeUsage的继承

在自定义特性中,命名参数Inherited=true,该命名参数指定所指示的特性能否由派生类和重写成员继承。

    /// <summary>
    /// 自定义特性(使用在方法和属性上,允许多次使用,默认inherited为true)
    /// </summary>
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true,Inherited=true)]
    public class Author : System.Attribute
    {
        public string AuthorName { get; set; }
        public string Version { get; set; }       
        public Author()
            : this(null, null)
        {

        }
        public Author(string authorName, string version)
        {
            this.AuthorName = authorName;
            this.Version = version;
        }
    }

 使用特性

     public class Sample_01
    {
        [Author()]
        public virtual void Method() { }
        [Author()]
        public virtual string Property { get; set; }
    }
    public class BaseClass1 : Sample_01
    {

    }
    public class BaseClass2 : Sample_01
    {
        public override void Method() { }
        public override string Property { get; set; }
    }

 使用反射观察,派生类继承基类的特性。

public static void Run()
{
       int a, b;
BaseClass1 s1 = new BaseClass1(); a = s1.GetType().GetMethod("Method").GetCustomAttributes(true).Length; b = s1.GetType().GetProperty("Property").GetCustomAttributes(true).Length; Console.WriteLine("1.inherited"); Console.WriteLine("Method GetCustomAttributes Length:{0}", a); //1 Console.WriteLine("Property GetCustomAttributes Length:{0}", b); //1 }

而在派生类重写基类的成员时,属性和事件的特性不被继承

public static void Run()
{
BaseClass2 s2 = new BaseClass2();
Console.WriteLine("2.override");
a = s2.GetType().GetMethod("Method").GetCustomAttributes(true).Length;
b = s2.GetType().GetProperty("Property").GetCustomAttributes(true).Length;
Console.WriteLine("Method GetCustomAttributes Length:{0}", a);   //1
Console.WriteLine("Property GetCustomAttributes Length:{0}", b); //0
}

网上解释是这样的,CLS无法搜索到覆盖的属性或事件上所继承的特性

解决方法如下,派生类下重新的属性不仅继承基类的特性,还有它自己的特性

 public   class   BaseClass 
{ 
       public   virtual   int   property 
       { 
           [Attribute1,Attribute2,   ...   Attribute100] 
           get{...} 
       } 
} 
 public   class   MyClass   :   BaseClass 
{ 
        public   override   int   property 
        { 
             [Attribute101] 
              get{...} 
         } 
} 

3.利用反射获取特性信息

//自定义特性
[AttributeUsage(AttributeTargets.Class)]
    class TableAttribute : Attribute
    {
        public TableAttribute() { }
        public TableAttribute(string name) { Name = name; }
        public string Name { get; set; }
    }
    [AttributeUsage(AttributeTargets.Property)]
    class ColumnsAttribute : Attribute
    {
        public string ColumnName { get; set; }
        public int Length { get; set; }
        public DataType ColumnType { get; set; }
        public ColumnsAttribute(string columnName, int length, DataType columnType)
        {
            ColumnName = columnName;
            Length = length;
            ColumnType = columnType;
        }
        public ColumnsAttribute(string columnName, int length)
            : this(columnName, length, DataType.Unknow)
        {

        }
        public ColumnsAttribute(string columnName)
            : this(columnName, 0, DataType.Unknow)
        {

        }
    }

 //实体类

    [Table("Student"),Serializable]
    public class Student
    {
        [Columns("StudentID", 20, DataType.Number)]
        public int StudentID
        { get; set; }

        [Columns("UserName", 10, DataType.Nvarchar2)]
        public string Name
        { get; set; }       
    }
 public static void Run()
        {
            Type t = typeof(Student);
            //类特性
            object[] attributes=t.GetCustomAttributes(typeof(TableAttribute),true);
            foreach (var attribute in attributes)
            {
                TableAttribute attr = attribute as TableAttribute;
                Console.WriteLine("表名:" + attr.Name);
            }            
            System.Reflection.PropertyInfo[] properties = t.GetProperties();
            foreach (var property in properties)
            {
                Console.WriteLine("属性名:" + property.Name);
                object[] arrays2 = property.GetCustomAttributes(typeof(ColumnsAttribute), true);
                foreach (var a in arrays2)
                {
                    Console.WriteLine("\t特性:" + ((ColumnsAttribute)a).ColumnName);
                }
            }           
        }

 

posted @ 2012-06-30 18:10  wind2013  阅读(117)  评论(0)    收藏  举报