ユーザー定義の属性 (C++ コンポーネント拡張)
カスタム属性は、インターフェイスのメタデータを、クラスまたは構造体、メソッド、パラメーター、または列挙型拡張することができます。
すべてのランタイム
すべてのランタイムはカスタム属性をサポートします。
Windows ランタイム
C++/CXの属性はプロパティのみをサポートしますが、コンストラクターまたはメソッドを使用してしません。
要件
コンパイラ オプション: /ZW
共通言語ランタイム
カスタム属性は、マネージの要素のメタデータを拡張することができます。詳細については、「属性を使用したメタデータの拡張」を参照してください。
解説
このトピックで示す情報と構文は attributeに示す情報に優先されるようになっています。
型を定義し、Attribute に型の基本クラスができ、オプションで AttributeUsageAttribute の属性を適用することで、カスタム属性を定義できます。
たとえば、Microsoft Transaction Server (MTS) 1.0でのトランザクションに関する動作、同期、負荷分散ODL、などのカスタム属性を使用して、タイプ ライブラリに挿入するカスタムGUIDによって指定されました。したがって、MTSサーバーのクライアントは、タイプ ライブラリを読み込むことによって特性を決定できます。.NET Frameworkでは、タイプ ライブラリの類似性がメタデータ内であり、ODLのカスタム属性の類似性は、カスタム属性です。また、タイプ ライブラリを読み込む場合に、型リフレクションと同様に使用できます。
詳細については、次のトピックを参照してください。
Visual C++のアセンブリの署名の詳細については、厳密名アセンブリ (アセンブリ署名) (C++/CLI)を参照してください。
要件
コンパイラ オプション: /clr
例
例
次の例ではカスタム属性を定義する方法を示します。
// user_defined_attributes.cpp
// compile with: /clr /c
using namespace System;
[AttributeUsage(AttributeTargets::All)]
ref struct Attr : public Attribute {
Attr(bool i){}
Attr(){}
};
[Attr]
ref class MyClass {};
例
次の例は、カスタム属性の主な機能を示します。たとえば、この例はカスタム属性の一般的な使用方法を示しています: クライアントに完全に記述できるサーバーをインスタンス化します。
// extending_metadata_b.cpp
// compile with: /clr
using namespace System;
using namespace System::Reflection;
public enum class Access { Read, Write, Execute };
// Defining the Job attribute:
[AttributeUsage(AttributeTargets::Class, AllowMultiple=true )]
public ref class Job : Attribute {
public:
property int Priority {
void set( int value ) { m_Priority = value; }
int get() { return m_Priority; }
}
// You can overload constructors to specify Job attribute in different ways
Job() { m_Access = Access::Read; }
Job( Access a ) { m_Access = a; }
Access m_Access;
protected:
int m_Priority;
};
interface struct IService {
void Run();
};
// Using the Job attribute:
// Here we specify that QueryService is to be read only with a priority of 2.
// To prevent namespace collisions, all custom attributes implicitly
// end with "Attribute".
[Job( Access::Read, Priority=2 )]
ref struct QueryService : public IService {
virtual void Run() {}
};
// Because we said AllowMultiple=true, we can add multiple attributes
[Job(Access::Read, Priority=1)]
[Job(Access::Write, Priority=3)]
ref struct StatsGenerator : public IService {
virtual void Run( ) {}
};
int main() {
IService ^ pIS;
QueryService ^ pQS = gcnew QueryService;
StatsGenerator ^ pSG = gcnew StatsGenerator;
// use QueryService
pIS = safe_cast<IService ^>( pQS );
// use StatsGenerator
pIS = safe_cast<IService ^>( pSG );
// Reflection
MemberInfo ^ pMI = pIS->GetType();
array <Object ^ > ^ pObjs = pMI->GetCustomAttributes(false);
// We can now quickly and easily view custom attributes for an
// Object through Reflection */
for( int i = 0; i < pObjs->Length; i++ ) {
Console::Write("Service Priority = ");
Console::WriteLine(static_cast<Job^>(pObjs[i])->Priority);
Console::Write("Service Access = ");
Console::WriteLine(static_cast<Job^>(pObjs[i])->m_Access);
}
}
出力
例
Object^の型は異なるデータ型を置き換えます。次の例では、パラメーターとしてObject^配列を受け取るカスタム属性を定義します。
属性の引数がコンパイル時定数である必要があります; ほとんどの場合、定数リテラル必要があります。
カスタム属性ブロックからSystem::Typeの値を返す方法については、typeid (C++ コンポーネント拡張) を参照してください。
// extending_metadata_e.cpp
// compile with: /clr /c
using namespace System;
[AttributeUsage(AttributeTargets::Class | AttributeTargets::Method)]
public ref class AnotherAttr : public Attribute {
public:
AnotherAttr(array<Object^>^) {}
array<Object^>^ var1;
};
// applying the attribute
[ AnotherAttr( gcnew array<Object ^> { 3.14159, "pi" }, var1 = gcnew array<Object ^> { "a", "b" } ) ]
public ref class SomeClass {};
例
ランタイムは、カスタム属性クラスのパブリック部分がシリアル化する必要があります。カスタム属性を作成するときに、カスタム属性の名前付き引数は、コンパイル定数だけです。(メタデータのクラス レイアウトに追加されたビットのシーケンスとして考えるとします。)
// extending_metadata_f.cpp
// compile with: /clr /c
using namespace System;
ref struct abc {};
[AttributeUsage( AttributeTargets::All )]
ref struct A : Attribute {
A( Type^ ) {}
A( String ^ ) {}
A( int ) {}
};
[A( abc::typeid )]
ref struct B {};