カスタム属性の宣言(RTTI)
属性:インデックス への移動
このトピックでは、カスタム属性の作成に使用する基本メソッド、属性クラスの適切な設計を行ううえでの決定事項、一般的な使用例について説明します。
属性の宣言
属性はシンプル クラス型です。独自のカスタム属性を宣言するには、特別な定義済みクラス System.TCustomAttribute から派生させる必要があります。たとえば以下のようにします。
type
MyCustomAttribute = class(TCustomAttribute)
end;
その後、たとえば以下のように、MyCustomAttribute
を使用して、任意の型またはある型(クラス、レコード、インターフェイスなど)の任意のメンバに注釈を付けることができます。
type
[MyCustomAttribute]
TSpecialInteger = type integer;
TSomeClass = class
[MyCustomAttribute]
procedure Work;
end;
なお、宣言される属性クラスは class abstract として宣言せず、抽象メソッドを含まないようにしてください。コンパイル上は、これらの属性を注釈に使用できるとしても、ビルド済みバイナリでは、出力される RTTI 情報にそれらは含まれません。
"Attribute" で終わる属性名の暗黙的短縮
次のように、同じ名前プレフィックスを持つ、TCustomAttribute
の 2 つのサブクラスを定義するとしましょう。ただし、一方は "Attribute" がサフィックスとして付いています。
MyCustom
MyCustomAttribute
"Attribute" サフィックスの付いたクラス(MyCustomAttribute
)が常に使用され、短縮名のクラス(MyCustom
)にはアクセスできなくなります。
以下のサンプル コードでは、この問題の例を示しています。この場合、TCustomAttribute
のサブクラス Test
が適用されるのではないかと思われるかもしれませんが、[Test]
か [TestAttribute]
のどちらかが使用される箇所では、暗黙の名前短縮のために実際にはもう一方の TestAttribute
が適用されます。
type
// あいまいさのある名前を調べる
TestAttribute = class(TCustomAttribute)
end;
// アクセスできなくなる
Test = class(TCustomAttribute)
end;
[Test] // 実行時に TestAttribute に解決される
TAmbigiousClass = class
end;
属性のコンストラクタ
通常、属性は、実行時に問い合わせ可能な何らかの追加情報を伝えることを目的としています。属性クラスのカスタム情報を指定できるようにするには、たとえば以下のように、属性クラスのコンストラクタを宣言する必要があります。
type
AttributeWithConstructor = class(TCustomAttribute)
public
constructor Create(const ASomeText: String);
end;
その後、これは次のように使用することができます。
type
[AttributeWithConstructor('Added text value!')]
TRecord = record
FField: Integer;
end;
メソッド解決は属性にも有効です。つまり、カスタム定義の属性にオーバーロード コンストラクタを定義できます。out
パラメータや var
パラメータではなく定数パラメータを受け取るコンストラクタのみ宣言します。これは属性の働きにおける基本的な制限事項に由来します。これについては、「型および型メンバの注釈付け」で詳しく説明します。