CustomAttribute
DESC
Class, Method に追加情報を与えるもの.
自分で新たな属性を作る場合は Attribute というクラスを継承して作成します。
POINT
NUnit は次のように解釈する。
// [TestFixture]属性であるMyTestはテストクラスである
[TestFixture]
public class MyTest {
// [Setup]属性であるInit()は各テストメソッドの開始前に呼ぶメソッドである
[SetUp]
public void Init() {
// 各テストメソッドが呼ばれる前に行う処理
}
// [Test]属性をもつメソッドはテストメソッドである
[Test]
public void Test1() {
// テスト処理
}
// [Test]属性をもつメソッドはテストメソッドである
[Test]
public void Test2() {
// テスト処理
}
}
namespace SampleCustomAttribute {
// 自作したクラス用の属性 MyClassAttribute
// -> なるほど ! 属性というクラスをつくるのか ^ ^/
[AttributeUsage(AttributeTargets.Class)]
class MyClassAttribute : Attribute {
private string name; // 名前
private bool isBool; //
public MyClassAttribute(string name) {
this.name = name;
}
// Accessor
public string Name {
get { return name; }
}
public bool IsBool {
get { return isBool; }
set { isBool = value; }
}
}
}
namespace SampleCustomAttribute {
// 自作したメソッド用の属性 MyMethodAttribute
// [ AttributeUsage(...) ]は属性クラスの頭に必ずつける。
[AttributeUsage(AttributeTargets.Method)]
class MyMethodAttribute : Attribute {
private string name;
public MyMethodAttribute(string name) {
this.name = name;
}
public string Name {
get { return name; }
}
}
}
(...) の中は、
クラスの属性の場合、AttributeTargets.Class
メソッドの属性の場合、AttributeTargets.Method
となります。
では、これらの属性を使ってみます。
namespace SampleCustomAttribute {
[MyClass("this is HogeClass")]
class HogeClass {
[MyMethod("this is Method1.")]
public void Method1() {
Console.WriteLine("MyClass Method1().");
}
}
}
HogeClass というクラスに属性 MyClassAttribute を、
Method1 に属性 MyMethodAttribute を付けました。
属性を付けるときは、
[MyClass("this is HogeClass")] のように Attribute を省略も
[MyClassAttribute("this is HogeClass")] のようにAttributeを付けることもできる。
Attribute は省くのが一般的。
MyClassAttribute, MyMethodAttribute はコンストラクタで引数を取るので、
属性を付ける際に引数を渡しています。
もし MyClassAttribute のコンストラクタの引数がゼロだった場合、
[MyClassAttribute]となる。
また MyClassAttribute のプロパティ IsBool は以下のように設定できる。
namespace SampleCustomAttribute {
// class に属性をつけた.
[MyClass("this is HogeClass", IsBool=true)]
class HogeClass {
// Method に属性をつける。
[MyMethod("this is Method1.")]
public void Method1() {
Console.WriteLine("MyClass Method1().");
}
}
}
IsBoolのようにsetを持つプロパティは、属性指定時に
プロパティ名 = 値
という風に書くことができます。
コンストラクタの引数 - 必須の引数
setをもつプロパティ - 必須でない引数
という風に使い分けると良いでしょう。
属性を読みだしてみる
属性を付けても、その属性を読み出せなければ意味がない。
主に リフレクション の機能を使う。
namespace SampleCustomAttribute {
class AttributeSearch {
// クラスのタイプから指定されている MyClassAttribute 属性を取り出す
// class の種類を指定するらしい.
public static MyClassAttribute[] GetMyClassAttribute( Type classType ) {
object[] ary = classType.GetCustomAttributes( typeof(MyClassAttribute), false );
// cast して返す.
return ( MyClassAttribute[] )ary;
}
// クラス名から指定されている MyClassAttribute 属性を取り出す
public static MyClassAttribute[] GetMyClassAttribute(string className) {
// 名前から, ClassType を取得する.
// Type とは class の種類のことらしい.
Type classType = Type.GetType( className );
// ↑のクラスに統合される.
return GetMyClassAttribute( classType );
}
// クラスのタイプとメソッド名から指定されている MyMethodAttribute 属性を取り出す
public static MyMethodAttribute[] GetMyMethodAttribute(Type classType, string methodName) {
MethodInfo info = classType.GetMethod(methodName);
object [] ary = info.GetCustomAttributes(typeof(MyMethodAttribute), false);
return (MyMethodAttribute[])ary;
}
}
}
1 つのクラス、メソッドに対して同じ属性を複数指定できるので
戻り値は属性の配列となる。
これらを使って MyClassから属性を取り出すことができる。
// Type は ↑で定義した CustomAttributeClass
MyClassAttribute[] myClassAttributes;
// static Method を利用して取得する.
myClassAttributes = AttributeSearch.GetMyClassAttribute( typeof(HogeClass) );
myClassAttributes = AttributeSearch.GetMyClassAttribute( "SampleCustomAttribute.MyClass" );
// Method を得る.
MyMethodAttribute[] myMethodAttributes;
myMethodAttributes = AttributeSearch.GetMyMethodAttribute(typeof(HogeClass), "Method1");