От: | NoOneKnows | ||
Дата: | 27.11.06 00:07 | ||
Оценка: | 70 (5) |
Think of the following simple example. If we want managed code to interoperate with classic COM applications, we need to play by the classic COM rules. One of these rules is that every exported interface must have a globally unique identifier, a GUID, assigned to it. The runtime generates GUIDs on the fly, but we might need not just any GUID but rather a specific GUID assigned to a class. What do we do? Add another field to the TypeDef record to store an offset in the #GUID stream? This would surely help to reduce the size of the metadata tables, especially when we consider that only a small fraction of all TypeDefs might ever be used in COM interoperation. To solve the problem, we can introduce a GUID-carrying custom attribute—actually, we have one already: System.Runtime.InteropServices.GuidAttribute—and assign this attribute to any TypeDef participating in the COM interoperation.
The ILAsm syntax for declaring a custom attribute is as follows:
.custom <attribute_type> [ = ( <hexbytes> ) ]
or, considering the limitation imposed on <attribute_type> in the first release of the common language runtime:
.custom instance void <class_ref>::.ctor(<arg_list>)
[ = ( <hexbytes> ) ]
where <class_ref> is a fully qualified class reference, <arg_list> is an argument list of the instance constructor, and <hexbytes> is the sequence of two-digit hexadecimal numbers representing the bytes in the custom attribute’s blob.
The Type entry of a custom attribute is a coded token of type CustomAttributeType and hence theoretically can be one of the following: TypeRef, TypeDef, Method, MemberRef, or String. In fact, in the first release of the common language runtime, the choice is limited to Method or MemberRef because of the requirement that the type of a custom attribute must be an instance constructor and nothing else. The class whose instance constructor represents the custom attribute type should be derived from the abstract class [mscorlib]System.Attribute.