Attributklasser för X++

Anmärkning

Intressegrupper för communityn har nu flyttat från Yammer till Microsoft Viva Engage. Om du vill gå med i en Viva Engage-community och delta i de senaste diskussionerna fyller du i formuläret Begär åtkomst till Finance and Operations Viva Engage Community och väljer den community som du vill ansluta till.

I den här artikeln beskrivs användningen av attribut i X++.

Ett attribut är en icke-abstrakt klass som utökar (ärver från) klassen SysAttribute . Attribut representerar eller lagrar metadata om typer och metoder. Ett attribut kan kopplas till en klass, ett klassfält, en klassmetod, ett gränssnitt eller en tabell.

Attribut tillämpas på hanterare av ombud och metoder för att mappa hanterare till dessa mål.

Skapa en attributklass

En attributklass kan utöka klassen SysAttribute direkt eller utöka alla underordnade till klassen SysAttribute . Klassen SysAttribute kan inte användas som ett attribut eftersom den deklareras som abstrakt. I följande exempel visas deklarationen och designen för en vanlig attributklass som du kan skapa.

public class PracticeAttribute extends SysAttribute
{
    // Fields in the classDeclaration.
    StartEnd startEndEnum;
    str reason;
    // Constructor.
    public void new(StartEnd _startEndEnum, str _reason)
    {
        startEndEnum  = _startEndEnum;
        reason = _reason;
    }
    // Other methods can go here.
}

Dekorera en klass med ett attribut

I följande exempel visas en klass och en metod som är dekorerad med PracticeAttribute som angavs i föregående exempel. Om konstruktorn för attributet inte tar några parametrar är parenteserna för parametrarna valfria. Attributdekorationen kan vara [AnotherAttribute] utan parenteser.

[PracticeAttribute(StartEnd::End, "Use the RegularClass class at the end.")]
public class RegularClass
{
    [PracticeAttribute(Startend::Start, "Use the rehearse method at the start.")]
    public int rehearse()
    {
        // Logic goes here.
    }
    // More fields and methods belong here.
}

Du kan utelämna suffixet för attributnamnet om suffixet är Attribute. Du kan till exempel använda [Practice] i stället [PracticeAttribute] i föregående exempel.

Attributkonstruktorer

Du kan göra så att attributklassen lagrar skräddarsydda metadata varje gång den används för att dekorera en klass genom att låta konstruktorn ta parametrar. Parametrarna för konstruktorn måste vara literaler av de primitiva typerna, till exempel int,enum eller str. Kompilatorn konstruerar inte någon instans av attributklassen. Den lagrar namnet på attributklassen, plus literalvärdena för konstruktorn. Om logiken i en attributkonstruktor skulle utlösa ett undantag skulle undantaget därför inte hittas genom att dekorera en klass med attributet . Undantaget skulle hittas senare när en process tittar på en klass för att se attributet som det är dekorerat med. Det är då attributet är konstruerat.

Namngivningskonventioner

Alla attributklasser har suffixattributet i sitt namn. Attributsuffixet är den namnkonvention som vi rekommenderar, men det är inte ett systemkrav. Du kan avgöra om en klass utökas direkt från SysAttribute genom att välja klassen i Application Explorer och granska egenskapen Extends i fönstret Egenskaper .

SysObsoleteAttribute

Systemet innehåller flera attribut, inklusive klassen SysObsoleteAttribute . En användning av klassen SysObsoleteAttribute är att meddela kompilatorn att kompilatorn ska misslyckas om en viss metod anropas i källkoden. Kompilatorn avvisar kompilatorn och visar det specifika meddelande som lagras i den här användningen av attributet. Klassen SysObsoleteAttribute kan också användas för att meddela kompilatorn att utfärda varningsmeddelanden i stället för fel.

SysObsoleteAttribute-kodexempel

[SysObsoleteAttribute("The Automobile class might have faster performance.", false)]
class Bicycle
{
    // Members of the Bicycle class go here.
}

Metadatareflektion

Du använder reflektion för att hitta attributmetadata som är kopplade till en klass. Klasserna som ska användas för attributreflektion är följande:

  • DictClass-klass – för klasser och gränssnitt.
  • DictMethod-klass – För metoder i klasser, gränssnitt eller tabeller.

I föregående reflektionsklasser är metoderna för att reflektera över attributmetadata följande:

  • getAllAttributes-metod
  • getAttribute-metod
  • getAttributedClasses-metod
  • getAttributes-metod

Anmärkning

Det finns ingen mekanism för att lista alla metoder eller klasser som är prydda med ett visst attribut från X++-kod. Eftersom X++-kompilatorn registrerar den här informationen i korsreferensdatabasen kan informationen dock mineras därifrån.

Exempel på kod för metadatareflektion

Du använder klassen DictMethod för att hitta metadatavärdet för ett attribut som är dekoration på en metod. I följande kodexempel används klassen SysEntryPointAttribute som attribut. Den accepterar parametervärdena för metodnamnet och för namnet på den klass som innehåller metoden. Metoden parmChecked är särskild för klassen SysEntryPointAttribute och den ärvs inte från basklassen SysAttribute. Varje attributklass kan ha ett eget metodnamn för sina metadata.

static public int MetadataOfSysEntryPointAttributeOnMethod
        (
        str _sNameOfClass,
        str _sNameOfMethod
        )
{
    // Return Values:
    // 0 == Has the attribute, its metadata value is false;
    // 1 == Has the attribute, its metadata value is true;
    // 2 == The method lacks the SysEntryPointAttribute.
    int nReturnValue = -1,
        nClassId;
    boolean boolParmChecked;
    DictMethod dm;
    Object attributeAsObject;
    SysEntryPointAttribute sepAttribute;
    Global::info("Starting AttributeReflection" 
        + " ::MetadataOfSysEntryPointAttributeOnMethod ....");
    Global::info(strFmt
        ("Parameters are: _sNameOfClass = %1 ,  _sNameOfMethod = %2 .", 
        _sNameOfClass, _sNameOfMethod)
        );
    nClassId = Global::className2Id(_sNameOfClass);
    dm = new DictMethod
        (UtilElementType::ClassInstanceMethod,
        nClassId,
        _sNameOfMethod
        );
    attributeAsObject = dm.getAttribute("SysEntryPointAttribute");
    if (attributeAsObject is SysEntryPointAttribute)
    {
        sepAttribute = attributeAsObject as SysEntryPointAttribute;
        boolParmChecked = sepAttribute.parmChecked();
        if (boolParmChecked)
            nReturnValue = 1;
        else
            nReturnValue = 0;
        Global::info(
            strFmt("Return value is %1.",
                nReturnValue)
            );
    }
    else
    {
        nReturnValue = 2;
        Global::error("Object is not a SysEntryPointAttribute??");
    }
    return nReturnValue;
}
/*** Output displayed in the Infolog.
Message (05:03:22 pm)
Starting AttributeReflection ::MetadataOfSysEntryPointAttributeOnMethod ....
Parameters are: _sNameOfClass = CustCustomerService ,  _sNameOfMethod = create .
Return value is 1.
***/
/**************
// Simple AOT > Jobs job to run the method.
static void AttributeReflection33Job(Args _args)
{
    AttributeReflection::MetadataOfSysEntryPointAttributeOnMethod
        ("CustCustomerService", "create");
}
**************/