Attributes provide a powerful method of associating metadata, or declarative information, with code (assemblies, types, methods, properties, and so forth).After an attribute is associated with a program entity, the attribute can be queried at run time by using a technique called reflection.
定制特性(Custom attribute)本质上是一个类型的实例。定制特性类必须直接或间接从公共抽象类System.Attribute派生。它是类的实例,在编译时被序列化成驻留在元数据中的字节流。在运行时,可对元数据进行反序列化,从而构造出类的实例。
特性有公共构造函数,且允许设置与特性类关联的公共字段或属性。构造器的参数称为定位参数(positional parameter),是强制性的(必选);用于设置字段或属性的“参数”称为命名参数(named parameter),是可选的。可将多个特性应用于一个目标元素,特性的顺序无关紧要。
定制特性(Custom attribute)本质上是一个类型的实例。定制特性类必须直接或间接从公共抽象类System.Attribute派生。它是类的实例,在编译时被序列化成驻留在元数据中的字节流。在运行时,可对元数据进行反序列化,从而构造出类的实例。
特性有公共构造函数,且允许设置与特性类关联的公共字段或属性。构造器的参数称为定位参数(positional parameter),是强制性的(必选);用于设置字段或属性的“参数”称为命名参数(named parameter),是可选的。可将多个特性应用于一个目标元素,特性的顺序无关紧要。
[DllImport("Kernel32", CharSet = CharSet.Auto, SetLastError = true)]
[assembly: SomeAttr] // Applied to assembly
[module: SomeAttr] // Applied to module
[type: SomeAttr] // Applied to type
sealed class SomeType<[typevar: SomeAttr] T> // Applied to generic type variable
{
[field: SomeAttr] // Applied to field
public int SomeField = 0;
[return: SomeAttr] // Applied to return value
[method: SomeAttr]
public int SomeMethod(
[param: SomeAttr] // Applied to parameter
int SomeParam)
{
return SomeParam;
}
[property: SomeAttr] // Applied to property
public string SomeProp {
[method: SomeAttr] // Applied to get accessor method
get { return null; }
}
[event: SomeAttr] // Applied to event
[field: SomeAttr] // Applied to compiler-generated field
[method: SomeAttr] // Applied to compiler-generated add & remove methods
public event EventHandler SomeEvent;
}
可以利用特性对代码进行说明(注释)或在代码设计或调试期间辅助开发。
一、条件特性
#define BUGED
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace MyAttribute
{
public class Program
{
static void Main(string[] args)
{
ToolKit.FunA();
ToolKit.FunB();
ToolKit.FunC();
ToolKit.FunD();
Console.ReadKey();
}
}
class ToolKit
{
[ConditionalAttribute("X")] // Attribute名称的长记法
[ConditionalAttribute("BUGED")]
public static void FunA()
{
Console.WriteLine("Created By X, Buged.");
}
[Conditional("X")] // Attribute名称的短记法
[Conditional("NOBUG")]
public static void FunB()
{
Console.WriteLine("Created By X, NoBug.");
}
[Conditional("Y")]
[Conditional("BUGED")]
public static void FunC()
{
Console.WriteLine("Created By Y, Buged.");
}
[Conditional("Y"), Conditional("NOBUG5")]
public static void FunD()
{
Console.WriteLine("Created By Y, NoBug.");
}
}
}
二、定制自己的特性
可以将特性想像成逻辑状态容器。特性类应该很简单,只提供一个公共构造器来接受特新的强制性(或定位性)状态信息,可以提供公共字段或属性以接受可选(或命名)状态信息。
// 自定义特性类
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true)]
internal class TestAttribute : Attribute
{
}
[Test]
[Serializable]
internal class BaseType
{
[Test]
protected virtual void DoSomething() { }
}
internal class DerivedType : BaseType
{
protected override void DoSomething() { }
}
如果自定义特性类时没有使用AttributeUsageAttribute, 编译器和CLR将假定该特性能应用于所有目标元素,而且可以继承。
AttributeUsageAttribute实现http://referencesource.microsoft.com/#System,namespaces
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: AttributeUsageAttribute
**
**
** Purpose: The class denotes how to specify the usage of an attribute
**
**
===========================================================*/
namespace System {
using System.Reflection;
/* By default, attributes are inherited and multiple attributes are not allowed */
[Serializable]
[AttributeUsage(AttributeTargets.Class, Inherited = true)]
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class AttributeUsageAttribute : Attribute
{
internal AttributeTargets m_attributeTarget = AttributeTargets.All; // Defaults to all
internal bool m_allowMultiple = false; // Defaults to false
internal bool m_inherited = true; // Defaults to true
internal static AttributeUsageAttribute Default = new AttributeUsageAttribute(AttributeTargets.All);
//Constructors
public AttributeUsageAttribute(AttributeTargets validOn) {
m_attributeTarget = validOn;
}
internal AttributeUsageAttribute(AttributeTargets validOn, bool allowMultiple, bool inherited) {
m_attributeTarget = validOn;
m_allowMultiple = allowMultiple;
m_inherited = inherited;
}
//Properties
public AttributeTargets ValidOn
{
get{ return m_attributeTarget; }
}
public bool AllowMultiple
{
get { return m_allowMultiple; }
set { m_allowMultiple = value; }
}
public bool Inherited
{
get { return m_inherited; }
set { m_inherited = value; }
}
}
}
AttributeTargets实现http://referencesource.microsoft.com/#System,namespaces
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
namespace System {
using System;
// Enum used to indicate all the elements of the
// VOS it is valid to attach this element to.
[Serializable]
[Flags]
[System.Runtime.InteropServices.ComVisible(true)]
public enum AttributeTargets
{
Assembly = 0x0001,
Module = 0x0002,
Class = 0x0004,
Struct = 0x0008,
Enum = 0x0010,
Constructor = 0x0020,
Method = 0x0040,
Property = 0x0080,
Field = 0x0100,
Event = 0x0200,
Interface = 0x0400,
Parameter = 0x0800,
Delegate = 0x1000,
ReturnValue = 0x2000,
//@todo GENERICS: document GenericParameter
GenericParameter = 0x4000,
All = Assembly | Module | Class | Struct | Enum | Constructor |
Method | Property | Field | Event | Interface | Parameter |
Delegate | ReturnValue | GenericParameter,
}
}<span style="font-size:18px;">
</span>
参考:《CLR via C#》
后面补充对反射的利用检测定制特性