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");