.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
- .NET之特性
- .NET之特性
- VB.NET特性之FieldOffset特性
- VB.NET特性之FieldOffset特性
- .NET之特性和属性
- ASP.NET 新特性之本地化
- ASP.NET 新特性之本地化
- .net核心高级特性之远程调用
- ADO.NET 新特性之SqlBulkCopy
- .NET之C#3.0中的新特性
- .NET高级特性总结之“委托”
- 黑马程序员-.NET基础之特性
- .net特性
- ASP.NET 2.0新特性之 URL映射
- .NET 3.x新特性之Lambda表达式
- 你必须知道的.NET之特性和属性(1)
- 你必须知道的.NET之特性和属性
- 你必须知道的.NET之特性和属性
- 查看文件时去除注释说明内容(原创贴-转载请注明出处)
- JAVA 基础语法——开发环境以及J2SE代码实现
- Apache设置页面认证(原创贴-转载请注明出处)
- Apache开启状态查看页面(原创贴-转载请注明出处)
- PHP优化笔记
- .NET之特性
- angularjs解析带换行\n的字符串
- apache2.4配置访问日志分割并过滤图片CSS等无用内容
- Mysql简单优化
- LVS简单介绍
- Qt+MSCV环境下配置外部库
- keepalived配置文件结构
- H5+JS+CSS3 实现圣诞情缘--学习心得1
- pragma comment的使用 pragma预处理指令详解