.NET之特性

来源:互联网 发布:淘宝杂货铺在哪儿 编辑:程序博客网 时间:2024/06/05 02:47

  1、什么是特性?

  MADN的定义为:公共语言运行时允许添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型、字段、方法和属性等。Attributes和Microsoft .NET Framework文件的元数据保存在一起,可以用来向运行时描述你的代码,或者在程序运行的时候影响应用程序的行为。

  通俗的理解为:特性本质上是一个类,为目标元素(程序集(assembly)、模块(module)、类型(type)、属性(property)、事件(event)、字段(field)、方法(method)、参数(param)、返回值(return)等)提供相关联的附加信息和处理这些信息的方法,并在运行期以反射的方式来获取这些附加信息或调用方法。

  定制特性以[,]形式展现,放在紧挨着的元素上,多个特性可以应用于同一元素,特性间以逗号隔开,以下表达规则有效:[AttributeUsage][ Flags]、[AttributeUsage, Flags]、[Flags, AttibuteUsageAttribute]、[AttributeUsage(), FlagesAttribute()]

  Atribute实例,是在编译期进行初始化,与目标元素一起作为元数据存储在程序集中。

  C#允许以指定的前缀来表示特性所应用的目标元素,建议这样来处理,因为显式处理可以消除可能带来的二义性。例如:

using System; 

namespace Anytao.net 

{
    [assembly: MyAttribute(
1)]          //应用于程序集
    [moduel: MyAttribute(2)]            //应用于模块
    pubic class Attribute_how2do
    {
        
//
    } 
}

  自己定义特性,必须直接或者间接的继承自System.Attribute类,而且必须有公有构造函数来创建其实例。

  所有自定义的特性名称都应该有个Attribute后缀,这是习惯性约定。

  定制特性也可以应用在其他定制特性上,这点也很好理解,因为定制特性本身也是一个类,遵守类的公有规则。例如很多时候我们的自定义定制特性会应用AttributeUsageAttribute特性,来控制如何应用新定义的特性。 [AttributeUsageAttribute(AttributeTarget.All),

[AttributeUsageAttribute(AttributeTarget.All),
AllowMultiple 
= true
Inherited 
= true]
class MyNewAttribute: System.Attribute
{
//

  定制特性不会影响应用元素的任何功能,只是约定了该元素具有的特质。

  所有非抽象特性必须具有public访问限制。

  特性常用于编译器指令,突破#define, #undefine, #if, #endif的限制,而且更加灵活。

  定制特性常用于在运行期获得代码注释信息,以附加信息来优化调试。

  定制特性可以应用在某些设计模式中,如工厂模式。

  定制特性还常用于位标记,非托管函数标记、方法废弃标记等其他方面。

  2、特性的应用

  2.1. 常用特性

  .NET框架中已经提供了丰富的固有特性由我们发挥,以下精选出我认为最常用、最典型的固有特性做以简单讨论。

       [Obsolete]

       一个程序在其生命周期中可能多次发布,后期版本更新中经常需要编写功能类似的新方法替换老方法,当希望使用新的方法但老的方法又不能删除时,如何提示程序员使用新的代码呢?此时,可使用Obsolete特性将元素标注为过期的,并在代码检查时显示有用的警告信息和替换方案。


  [AttributeUsage]

  AttributeUsage特性用于控制如何应用自定义特性到目标元素。关于AttributeTargets、AllowMultiple、Inherited、ValidOn,请参阅示例说明和其他文档。我们已经做了相当的介绍和示例说明,我们还是在实践中自己体会更多吧。

  [Flags]

  以Flags特性来将枚举数值看作位标记,而非单独的数值,例如:

enum Animal
{
    Dog     
= 0x0001,
    Cat     
= 0x0002,
    Duck    
= 0x0004,
  Chicken 
= 0x0008
}

  因此,以下实现就相当轻松,

Animal animals = Animal.Dog | Animal.Cat;
Console.WriteLine(animals.ToString());

  请猜测结果是什么,答案是:"Dog, Cat"。如果没有Flags特别,这里的结果将是"3"。关于位标记,也将在本系列的后续章回中有所交代,在此只做以探讨止步。

  [DllImport]

  DllImport特性,可以让我们调用非托管代码,所以我们可以使用DllImport特性引入对Win32 API函数的调用,对于习惯了非托管代码的程序员来说,这一特性无疑是救命的稻草。

using System;
using System.Runtime.InteropServices;

namespace Anytao.net
{
    
class MainClass 
    {
       [DllImport(
"User32.dll")]
       
public static extern int MessageBox(int hParent, string msg, string caption, int type);

       
static int Main() 
       {
          
return MessageBox(0"How to use attribute in .NET""Anytao_net"0);
      }
    }
}

  [Serializable]

  Serializable特性表明了应用的元素可以被序列化(serializated),序列化和反序列化是另一个可以深入讨论的话题,在此我们只是提出概念。

  [Conditional]

  Conditional特性允许我们包括或取消特定方法的所有调用,为方法声明应用Conditional特性并把编译符作为参数来使用。注意:Conditional不可应用于数据成员和属性。


当存在宏定义“DoTrace”时,函数才会被各处调用。

  还有其他的重要特性,包括:Description、DefaultValue、Category、ReadOnly、BrowerAble等,有时间可以深入研究。

  2.2. 自定义特性

  既然attribute,本质上就是一个类,那么我们就可以自定义更特定的attribute来满足个性化要求,只要遵守上述的12条规则,实现一个自定义特性其实是很容易的,典型的实现方法为:

using System;
using System.Reflection;                                 //应用反射技术获得特性信息

namespace Anytao.net
{
    
//定制特性也可以应用在其他定制特性上,
    
//应用AttributeUsage,来控制如何应用新定义的特性
    [AttributeUsageAttribute(AttributeTargets.All,       //可应用任何元素
        AllowMultiple = true,                            //允许应用多次
        Inherited = false)]                              //不继承到派生类
    
//特性也是一个类,
    
//必须继承自System.Attribute类,
    
//命名规范为:"类名"+Attribute。        
    public class MyselfAttribute : System.Attribute
    {
        
//定义字段
        private string _name;
        
private int _age;
        
private string _memo;

        
//必须定义其构造函数,如果不定义有编译器提供无参默认构造函数
        public MyselfAttribute()
        {
        }
        
public MyselfAttribute(string name, int age)
        {
            _name 
= name;
            _age 
= age;
        }

        
//定义属性
        
//显然特性和属性不是一回事儿
        public string Name
        {
            
get { return _name == null ? string.Empty : _name; }
        }

        
public int Age
        {
            
get { return _age; }
        }

        
public string Memo
        {
            
get { return _memo; }
            
set { _memo = value; }
        }

        
//定义方法
        public void ShowName()
        {
            Console.WriteLine(
"Hello, {0}", _name == null ? "world." : _name);
        }
    }

    
//应用自定义特性
    
//可以以Myself或者MyselfAttribute作为特性名
    
//可以给属性Memo赋值
    [Myself("Emma"25, Memo = "Emma is my good girl.")]
    
public class Mytest
    {
        
public void SayHello()
        {
            Console.WriteLine(
"Hello, my.net world.");
        }
    }

    
public class Myrun
    {
        
public static void Main(string[] args)
        {
            
//如何以反射确定特性信息
            Type tp = typeof(Mytest);
            MemberInfo info 
= tp;
            MyselfAttribute myAttribute 
=
                (MyselfAttribute)Attribute.GetCustomAttribute(info, 
typeof(MyselfAttribute));
            
if (myAttribute != null)
            {
                
//嘿嘿,在运行时查看注释内容,是不是很爽
                Console.WriteLine("Name: {0}", myAttribute.Name);
                Console.WriteLine(
"Age: {0}", myAttribute.Age);
                Console.WriteLine(
"Memo of {0} is {1}", myAttribute.Name, myAttribute.Memo);
                myAttribute.ShowName();
            }

            
//多点反射
            object obj = Activator.CreateInstance(typeof(Mytest));

            MethodInfo mi 
= tp.GetMethod("SayHello");
            mi.Invoke(obj, 
null);
            Console.ReadLine();
        }
    }
}

结语:

  MSDN认为,特性 (Attribute) 描述如何将数据序列化,指定用于强制安全性的特性,并限制实时 (JIT) 编译器的优化,从而使代码易于调试。属性 (Attribute) 还可以记录文件名或代码作者,或在窗体开发阶段控制控件和成员的可见性。

  dudu Boss收藏的系列文章《Attribute在.net编程中的应用》,给你应用方面的启示会很多,值得研究。

  亚历山大同志 的系列文章《手把手教你写ORM(六)》中,也有很好的诠释。

  idior的文章《Remoting基本原理及其扩展机制》也有收获,因此补充。

引用:http://dev.yesky.com/msdn/138/7558138.shtml

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 儿子今晚后妈随便你怎么弄说说 同学说要看我骑他妈我说可以 荒村野性全文阅读目录 小成和后妈全文免费阅读文章 小诚和后妈全文免费阅读 娘亲在玉米地河边 我和娘亲玉米 娘亲给儿生个娃大结局 在玉米地插娘亲短文 在玉米地插娘亲电影 王来地里与娘激战2 在玉米地插娘亲播放 孩子别谢了我是你妈 臭小子 别急妈咪又不是不给你 粉嫩娘亲全文阅读全文 你的好粗妈v好痛 乡村孽缘上了王雪琴101一0 乡村小神医之情缠玉米地 乡村孽缘长篇小说全文免费阅读 乡村孽缘王雪琴怀孕是第几章 桃花村傻牛李大根 拨出来你爸要来 一个山村全家小说全集 乡村孽缘胡秀`小说全集 儿子小点声别让你爸听见长篇小说 胡秀英全文费阅读全文 儿子小声点别让你爸听见小说 乡村浪子的孽缘大伯母 畜牲别让你爸听见在线小说阅读 胡秀英乡全文免费阅读 婶的肥田全文免费阅读 乡村孽缘 王雪琴 熟花母芬芳泌蜜全文阅读 中文字字幕23页在线 单身娘亲有肥田 中文字字幕125页 中文字幕天堂网 中文字126幕中文字页幕 学生的母亲3字幕中文翻译 中幕文字36页 影音先锋欧美日韩片