您的位置:首页 > 编程语言 > C#

C# 特性(Attribute)

2016-01-10 21:59 786 查看
Attributes provide a powerful method of associating metadata, or declarative information, with code (
4000
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),是可选的。可将多个特性应用于一个目标元素,特性的顺序无关紧要。
[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#》

后面补充对反射的利用检测定制特性
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: