Metadata Using - Attributes
範例如下
using System;
namespace ConsoleApp1
{
[System.AttributeUsage(System.AttributeTargets.Class |
System.AttributeTargets.Struct,
AllowMultiple = true,
Inherited = true)]
public class AuthorAttribute : System.Attribute
{
string name;
public double version;
public AuthorAttribute(string name)
{
this.name = name;
// Default value.
version = 1.0;
}
public string GetName()
{
return name;
}
}
// Class with the Author attribute.
[Author("P. Ackerman")]
public class FirstClass
{
// ...
}
// Class without the Author attribute.
public class SecondClass
{
// ...
}
// Class with multiple Author attributes.
[Author("R. Koch", version = 2.0), Author("P. Ackerman")]
public class ThirdClass
{
// ...
}
class TestAuthorAttribute
{
public static void Test()
{
PrintAuthorInfo(typeof(FirstClass));
PrintAuthorInfo(typeof(SecondClass));
PrintAuthorInfo(typeof(ThirdClass));
}
private static void PrintAuthorInfo(System.Type t)
{
System.Console.WriteLine("Author information for {0}", t);
// Using reflection.
System.Attribute[] attrs = System.Attribute.GetCustomAttributes(t); // Reflection.
// Displaying output.
foreach (System.Attribute attr in attrs)
{
if (attr is AuthorAttribute)
{
AuthorAttribute a = (AuthorAttribute)attr;
System.Console.WriteLine(" {0}, version {1:f}", a.GetName(), a.version);
}
}
}
}
class Program
{
static void Main(string[] args)
{
TestAuthorAttribute TestAuthorAttribute = new TestAuthorAttribute();
TestAuthorAttribute.Test();
Console.ReadKey();
}
}
/* Output:
Author information for FirstClass
P. Ackerman, version 1.00
Author information for SecondClass
Author information for ThirdClass
R. Koch, version 2.00
P. Ackerman, version 1.00
*/
}
注意要點分成三個部份,自訂 Attribute、套用 Attribute、處理 Attribute。
一、自訂 Attribute
1、自訂 Attribute 時,類別必須繼承 System.Attribute。
2、可以利用 System.AttributeUsage 來設定 ValidOn、AllowMultiple、Inherited 三個參數。
3、ValidOn 參數的套用,可以對自訂 Attribute 作出應用限制,ValidOn 參數是指 AttributeTargets Enum,
預設值是 AttributeTargets.All。
4、AllowMultiple 預設值為 false,Inherited 預設值為 true。
5、另一種對自訂 Attribute 作出應用限制,是指 Attribute targets。
[type: System.AttributeUsage(System.AttributeTargets.Class |
System.AttributeTargets.Struct,
AllowMultiple = true,
Inherited = true)]
public class AuthorAttribute : System.Attribute
{
string name;
public double version;
public AuthorAttribute(string name)
{
this.name = name;
// Default value.
version = 1.0;
}
public string GetName()
{
return name;
}
}
Target value | Applies to |
---|---|
assembly | Entire assembly |
module | Current assembly module |
field | Field in a class or a struct |
event | Event |
method | Method or 「get」 and 「set」 property accessors |
param | Method parameters or 「set」 property accessor parameters |
property | Property |
return | Return value of a method, property indexer, or 「get」 property accessor |
type | Struct, class, interface, enum, or delegate |
而有定義 Attribute targets 時,AttributeUsage 的 ValidOn 參數的設定可能會被忽略?
二、套用 Attribute
1、自訂 Attribute 名稱時,名稱的命名慣例可以帶有 Attribute 字尾;
而在套用 Attribute 名稱時,也可以省略 Attribute 字尾。
2、自訂 Attribute 的 class 一定要為 public,才能被他人使用。
3、Attribute 除了可以套在 class 上之外,也可以套在方法上;
而在 C# 7.3 更加可以套在 property、field 上。
using System;
using System.Reflection;
// An enumeration of animals. Start at 1 (0 = uninitialized).
public enum Animal
{
// Pets.
Dog = 1,
Cat,
Bird,
}
// A custom attribute to allow a target to have a pet.
public class AnimalTypeAttribute : Attribute
{
// The constructor is called when the attribute is set.
public AnimalTypeAttribute(Animal pet)
{
thePet = pet;
}
// Keep a variable internally ...
protected Animal thePet;
// .. and show a copy to the outside world.
public Animal Pet
{
get { return thePet; }
set { thePet = value; }
}
}
// A test class where each method has its own pet.
class AnimalTypeTestClass
{
[AnimalType(Animal.Dog)]
public void DogMethod() { }
[AnimalType(Animal.Cat)]
public void CatMethod() { }
[AnimalType(Animal.Bird)]
public void BirdMethod() { }
}
class DemoClass
{
static void Main(string[] args)
{
AnimalTypeTestClass testClass = new AnimalTypeTestClass();
Type type = testClass.GetType();
// Iterate through all the methods of the class.
foreach (MethodInfo mInfo in type.GetMethods())
{
// Iterate through all the Attributes for each method.
foreach (Attribute attr in
Attribute.GetCustomAttributes(mInfo))
{
// Check for the AnimalType attribute.
if (attr.GetType() == typeof(AnimalTypeAttribute))
Console.WriteLine(
"Method {0} has a pet {1} attribute.",
mInfo.Name, ((AnimalTypeAttribute)attr).Pet);
}
}
Console.ReadKey();
}
}
/*
* Output:
* Method DogMethod has a pet Dog attribute.
* Method CatMethod has a pet Cat attribute.
* Method BirdMethod has a pet Bird attribute.
*/
三、處理 Attribute
主要的關鍵在於 Attribute.GetCustomAttribute、
Attribute.GetCustomAttributes、Type.GetMethods、
Type.GetProperties、Type.GetConstructors 方法的使用。
參考資料: