description | title | ms.date | ms.topic | helpviewer_keywords | ms.assetid | ||
---|---|---|---|---|---|---|---|
Learn more about: User-Defined Attributes (C++/CLI and C++/CX) | User-Defined Attributes (C++/CLI and C++/CX) | 10/12/2018 | reference |
| 98b29048-a3ea-4698-8441-f149cdaec9fb |
C++/CLI and C++/CX enable you to create platform-specific attributes that extend the metadata of an interface, class or structure, method, parameter, or enumeration. These attributes are distinct from the standard C++ attributes.
You can apply C++/CX attributes to properties, but not to constructors or methods.
Compiler option: /ZW
The information and syntax presented in this topic is meant to supersede the information presented in attribute.
You can define a custom attribute by defining a type and making xref:System.Attribute a base class for the type and optionally applying the xref:System.AttributeUsageAttribute attribute.
For more information, see:
For information on signing assemblies in Visual C++, see Strong Name Assemblies (Assembly Signing) (C++/CLI).
Compiler option: /clr
The following sample shows how to define a custom attribute.
// user_defined_attributes.cpp// compile with: /clr /cusingnamespaceSystem; [AttributeUsage(AttributeTargets::All)] ref structAttr : publicAttribute { Attr(bool i){} Attr(){} }; [Attr] ref classMyClass {};
The following example illustrates some important features of custom attributes. For example, this example shows a common usage of the custom attributes: instantiating a server that can fully describe itself to clients.
// extending_metadata_b.cpp// compile with: /clrusingnamespaceSystem;usingnamespaceSystem::Reflection; public enumclassAccess { Read, Write, Execute }; // Defining the Job attribute: [AttributeUsage(AttributeTargets::Class, AllowMultiple=true )] public ref classJob : Attribute { public: property int Priority { voidset( int value ) { m_Priority = value; } intget() { return m_Priority; } } // You can overload constructors to specify Job attribute in different waysJob() { m_Access = Access::Read; } Job( Access a ) { m_Access = a; } Access m_Access; protected:int m_Priority; }; interface structIService { voidRun(); }; // 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 structQueryService : publicIService { virtualvoidRun() {} }; // Because we said AllowMultiple=true, we can add multiple attributes [Job(Access::Read, Priority=1)] [Job(Access::Write, Priority=3)] ref structStatsGenerator : publicIService { virtualvoidRun( ) {} }; intmain() { 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); } }
Service Priority = 0 Service Access = Write Service Priority = 3 Service Access = Write Service Priority = 1 Service Access = Read
The Object^
type replaces the variant data type. The following example defines a custom attribute that takes an array of Object^
as parameters.
Attribute arguments must be compile-time constants; in most cases, they should be constant literals.
See typeid for information on how to return a value of System::Type from a custom attribute block.
// extending_metadata_e.cpp// compile with: /clr /cusingnamespaceSystem; [AttributeUsage(AttributeTargets::Class | AttributeTargets::Method)] public ref classAnotherAttr : publicAttribute { 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 classSomeClass {};
The runtime requires that the public part of the custom attribute class must be serializable. When authoring custom attributes, named arguments of your custom attribute are limited to compile-time constants. (Think of it as a sequence of bits appended to your class layout in the metadata.)
// extending_metadata_f.cpp// compile with: /clr /cusingnamespaceSystem; ref structabc {}; [AttributeUsage( AttributeTargets::All )] ref structA : Attribute { A( Type^ ) {} A( String ^ ) {} A( int ) {} }; [A( abc::typeid )] ref structB {};