Field Metadata

Field Metadata

To define a field, you must first provide basic information: the field’s name and signature and flags indicating the field’s characteristics, stored in the Field metadata table. Then comes optional information, specific to certain kinds of fields: field marshaling information, found in the FieldMarshal table; field layout information in the FieldLayout table; field mapping information in the FieldRVA table; and a default value in the Constant table.

To reference a field, you must know its owner—TypeRef, TypeDef, or ModuleRef—as well as the field’s name and signature. The references to the fields are kept in the MemberRef table. The general structure of the field metadata group is shown in Figure 8-1.

Figure 8-1 Field metadata group.

The central metadata table of the group, the Field table, has the associated token type mdtFieldDef (0x04000000). A record in this table has three entries:

  • Flags (2-byte unsigned integer)  Binary flags indicating the field’s characteristics.

  • Name (offset in the #Strings stream)  The field’s name.

  • Signature (offset in the #Blob stream)  The field’s signature.

As you can see, a Field record does not contain one vital piece of information: which class or value type owns the field. The information about field ownership is furnished by the class descriptor itself: records in the TypeDef table have FieldList entries, which hold the RID (record index) of the Field table where the type’s fields can be found.

In the simplest case, when only the Field metadata table is involved, the IL assembly language (ILAsm) syntax for a field declaration is as follows:

.field <flags> <type> <name>

The owner of a field is the class or value type in the lexical scope of which the field is defined.

A field’s binary flags are defined in the CorHdr.h file in the enumeration CorFieldAttr and can be divided into four groups, as described in the following list. I’m using ILAsm keywords instead of the constant names from CorFieldAttr, as I don’t think the constant names are relevant.

  • Accessibility flags (mask 0x0007):

    • privatescope (0x0000)  This is the default accessibility. A private scope field is exempt from the requirement of having a unique triad of owner, name, and signature and hence must always be referenced by a FieldDef token and never by a MemberRef token (0x0A000000). Otherwise, this accessibility is the same as that specified by the private flag.

    • private (0x0001)  The field is accessible from its owner and from classes nested in the field’s owner.

    • famandassem (0x0002)  The field is accessible from types belonging to the owner’s family—that is, the owner itself and all its descendants—defined in the current assembly.

    • assembly (0x0003)  The field is accessible from types defined in the current assembly.

    • family (0x0004)  The field is accessible from the owner’s family.

    • famorassem (0x0005)  The field is accessible from the owner’s family and from all types defined in the current assembly.

    • public (0x0006)  The field is accessible from any type.

  • Contract flags (mask 0x02F0):

    • static (0x0010)  The field is static, shared by all instances of the type.

    • initonly (0x0020)  The field can only be initialized and cannot be written to later. Initialization takes place in an instance constructor (.ctor) for instance fields and in a class constructor (.cctor) for static fields.

    • literal (0x0040)  The field is a compile-time constant. The loader does not lay out this field and does not create an internal handle for it. The field cannot be directly addressed from IL and can be used only as a Reflection reference to retrieve an associated metadata-held constant. If you try to access a literal field directly—for example, through the ldsfld instruction—the JIT (just-in-time) compiler throws a MissingField exception and aborts the task.

    • notserialized (0x0080)  The field does not have to be serialized when the owner is remoted. This flag has meaning only for instance fields of the serializable types.

    • specialname (0x0200)  The field is special in some way, as defined by the name.

  • Interoperability flag:

    • pinvokeimpl (0x2000)  The field is unmanaged and is accessed from the managed code via the platform invocation mechanism (P/Invoke). In the first release of the Microsoft .NET common language runtime, the P/Invoke mechanism works for methods only, so this flag should never be set. ILAsm does not allow the flag to be set.

  • Reserved flags (cannot be set explicitly; mask 0x9500):

    • rtspecialname (0x0400)  The field has a special name that is reserved for the internal use of the common language runtime. Two field names are reserved: value_, for instance fields in enumerators; and _Deleted*, for fields marked for deletion but not actually removed from metadata. The keyword rtspecialname is ignored by the ILAsm compiler and is displayed by the IL Disassembler for informational purposes only. This flag must be accompanied by a specialname flag.

    • marshal(<native_type>) (0x1000)  The field has an associated FieldMarshal record specifying how the field must be marshaled when consumed by unmanaged code. The ILAsm construct marshal(<native_type>) defines the marshaling information emitted to the FieldMarshal table but does not set the flag directly. Rather, the flag is set behind the scenes by the metadata emission API when the marshaling information is emitted. Native types are discussed in Chapter 7, “Primitive Types and Signatures.”

    • [no ILAsm keyword] (0x8000)  The field has an associated Constant record. The flag is set by the metadata emission API when the respective Constant record is emitted. See the section “Default Values,” later in this chapter.

    • [no ILAsm keyword] (0x0100)  The field is mapped to data and has an associated FieldRVA record. The flag is set by the metadata emission API when the respective FieldRVA record is emitted. See the section “Mapped Fields,” later in this chapter.

In the field declaration, the type of the field (<type>) is the ILAsm notation of the appropriate single encoded type, which together with the calling convention forms the field’s signature. If you forgot what a field signature looks like, see the section “Field Signatures,” in Chapter 7.

The name of the field (<name>), also included in the declaration, should be a simple name. ILAsm does not allow composite field names, although one can always cheat and put a composite name in single quotation marks, turning it into a simple name.

Examples of field declarations include the following:

.field public static marshal(int) int32 I .field family string S .field private int32& pJ   // ERROR! ByRef in field signature!

Field references in ILAsm have the following notation:

<field_ref> ::= <field_type>[<class_ref>::]<field_name>

where <class_ref>—as we know from Chapter 6, “Namespaces and Classes”—is defined as

<class_ref> ::= [<resolution_scope>]<full_type_name>

where

 <resolution_scope> ::= [<assembly_ref_alias>]                          [.module <module_ref_name>]

For instance, this example uses the IL instruction ldfld, which loads the field value on the stack:

ldfld  int32 [.module Another.dll]Foo.Bar::idx

When it is difficult to infer from the context whether the referenced member is a field or a method, <field_ref> is sometimes preceded by the keyword field. Note that the keyword does not contain a leading dot. This example uses the IL instruction ldtoken, which loads an item’s runtime handle on the stack:

ldtoken field int32 [.module Another.dll]Foo.Bar::idx

The field references reside in the MemberRef metadata table, which has associated token type 0x0A000000. A record of this table has only three entries:

  • Class (coded token of type MemberRefParent)  This entry references the TypeRef or the ModuleRef table. Method references, residing in the same table, can have their Class entries referencing the Method and the TypeSpec tables as well.

  • Name (offset in the #Strings stream)

  • Signature (offset in the #Blob stream)



Inside Microsoft. NET IL Assembler
Inside Microsoft .NET IL Assembler
ISBN: 0735615470
EAN: 2147483647
Year: 2005
Pages: 147
Authors: SERGE LIDIN

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net