.NET基础 (18)特性

特性
1 什么是特性,如何自定义一个特性
2 .NET中特性可以在哪些元素上使用
3 有哪几种方法可以获知一个元素是否申明某个特性
4 一个元素是否可以重复申明同一个特性

 

特性
1 什么是特性,如何自定义一个特性

特性是一种特殊的用以申明式编程的机制,特性类型是一族继承自System.Attribute的类型,在编译时,特性的使用会被写入元数据中,以共运行或者程序中的反射使用。自定义一个特性,本质上是定义一个继承自System.Attribute的类型。

自定义特性示例:

    /// <summary>
    /// 自定义的特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Class)]
    public class MyAttribute : Attribute
    {
        private String _classname;
        public MyAttribute(String s)
        {
            _classname = s;
        }
        //一个只读属性
        public String ClassName
        {
            get
            {
                return _classname;
            }
        }
    }

    /// <summary>
    /// 使用自定义属性
    /// </summary>
    [MyAttribute("UseMyAttribute")]
    class UseMyAttribute
    {
        static void Main(string[] args)
        {
            Type t = typeof(UseMyAttribute);
            Object[] attributes = t.GetCustomAttributes(false);
            MyAttribute att = (MyAttribute)attributes[0];
            Console.WriteLine(att.ClassName);
            Console.Read();
        }
    }

输出:

UseMyAttribute

特性将被写入元数据中,所以特性的使用基本都基于反射机制。

有几点需要注意:

  • 按照惯例,特性的名字都以Attribute结尾。
  • C#中,为了使用方便,可以省略特性名字后缀Attribute,如 [MyAttribute("UseMyAttribute")] 可写为 [My("UseMyAttribute")]。
  • 特性自身可以添加其他特性。


2 .NET中特性可以在哪些元素上使用

特性可以应用在程序集、模块、结构、枚举、构造方法、方法、属性、字段、事件、接口、参数、委托、返回参数和泛型参数这些目标元素上。通过AttributeUsage特性可以限制自定义特性的使用范围。

示例:

using System;

//应用在程序集上
[assembly: MyAttribute]
//应用在模块上
[module: MyAttribute]

//应用在类型上
[type: MyAttribute]
class AttributeTargets<[typevar: MyAttribute] T> //泛型参数上
{
    //应用在字段上
    [field: MyAttribute]
    private String _MyString;

    //应用在构造方法上
    [method: MyAttribute]
    public AttributeTargets()
    {
    }

    //应用在属性上
    [property: MyAttribute]
    public String MyString
    {
        get
        {
            return _MyString;
        }
    }

    //应用在方法上
    [return: MyAttribute]
    public String Format(
        //应用在方法参数上
        [param: MyAttribute]String f)
    {
        return null;
    }

    //应用在事件上
    [event: MyAttribute]
    public event EventHandler MyEvent;
}

/// <summary>
/// 一个空的特性
/// 可用于所有元素
/// </summary>
public class MyAttribute : System.Attribute
{
}

public class MainClass
{
    static void Main(string[] args)
    {
    }
}

 

 


3 有哪几种方法可以获知一个元素是否申明某个特性

System.Attribute.IsDefined

System.Attribute.GetCustomAttribute

System.Attribute.GetCustomAttributes

System.Reflection.CustomAttributeData

示例:

    [My("GetAttributes")]
    class GetAttributes
    {
        static void Main(string[] args)
        {
            Type attributeType = typeof(MyAttribute);
            Type thisClass = typeof(GetAttributes);

            //使用IsDefined方法
            bool defined = Attribute.IsDefined(
                        thisClass,
                        attributeType);
            Console.WriteLine(
                 "GetAttributes类型是否申明了MyAttribute特性:{0}",
                 defined.ToString());

            //使用Attribute.GetCustomAttribute方法
            Attribute att = Attribute.GetCustomAttribute(
                        thisClass,
                        attributeType);
            if (att != null)
            {
                Console.WriteLine(
                    "GetAttributes类型申明了MyAttribute特性。");
                Console.WriteLine("名字为:{0}",
                     ((MyAttribute)att).Name);
            }

            //使用Attribute.GetCustomAttributes方法
            Attribute[] atts = Attribute.GetCustomAttributes(
                            thisClass,
                            attributeType);
            if (atts.Length > 0)
            {
                Console.WriteLine(
                     "GetAttributes类型申明了MyAttribute特性。");
                Console.WriteLine("名字为:{0}",
                     ((MyAttribute)atts[0]).Name);
            }

            //使用System.Reflection.CustomAttributeData类型
            IList<CustomAttributeData> list =
                CustomAttributeData.GetCustomAttributes(thisClass);
            if (list.Count > 0)
            {
                Console.WriteLine(
                     "GetAttributes类型申明了MyAttribute特性。");
                //注意这里可以对特性进行分析,但不能得到其实例
                CustomAttributeData attdata = list[0];
                Console.WriteLine("特性的名字是:{0}",
                      attdata.Constructor.DeclaringType.Name);
                Console.WriteLine("特性的构造方法有{0}个参数。",
                    attdata.ConstructorArguments.Count);
            }
            Console.Read();
        }
    }

    /// <summary>
    /// 一个简单的特性
    /// </summary>
    [AttributeUsage(AttributeTargets.All)]
    public sealed class MyAttribute : Attribute
    {
        private String _name;
        public MyAttribute(String s)
        {
            _name = s;
        }
        public String Name
        {
            get
            {
                return _name;
            }
        }
    }

 

输出:

GetAttributes类型是否申明了MyAttribute特性:True
GetAttributes类型申明了MyAttribute特性。
名字为:GetAttributes
GetAttributes类型申明了MyAttribute特性。
名字为:GetAttributes
GetAttributes类型申明了MyAttribute特性。
特性的名字是:MyAttribute
特性的构造方法有1个参数。

4 一个元素是否可以重复申明同一个特性

当一个特性申明了AttributeUsage特性并且显示地将AllowMultiple属性设置为true时,该特性就可以在同一元素上多次申明,否则的话编译器将被报错。

示例:

    [My("Class1")]
    [My("Class2")]
    [My("Class1")]
    class AllowMultiple
    {
        static void Main(string[] args)
        {
        }
    }

    /// <summary>
    /// 使用AttributeUsage限定使用范围
    /// 并且允许在同一元素上多次申明
    /// </summary>
    [AttributeUsage(AttributeTargets.Class,AllowMultiple=true)]
    class MyAttribute : Attribute
    {
        private String _s;

        public MyAttribute(String s)
        {
            _s = s;
        }
    }

 

 

 

转载请注明出处:

作者:JesseLZJ
出处:http://jesselzj.cnblogs.com

posted @ 2015-09-12 15:29  JesseLZJ  阅读(351)  评论(0编辑  收藏  举报