Udostępnij przez


Klasy atrybutów w języku X++

Uwaga / Notatka

Grupy zainteresowań społeczności zostały teraz przeniesione z usługi Yammer do aplikacji Microsoft Viva Engage. Aby dołączyć do społeczności Viva Engage i wziąć udział w najnowszych dyskusjach, wypełnij formularz Żądanie dostępu do aplikacji Finance and Operations Viva Engage Community i wybierz społeczność, którą chcesz dołączyć.

W tym artykule opisano użycie atrybutów w języku X++.

Atrybut jest klasą nie abstrakcyjną, która rozszerza (dziedziczy) klasę SysAttribute . Atrybuty reprezentują lub przechowują metadane dotyczące typów i metod. Atrybut można dołączyć do klasy, pola klasy, metody klasy, interfejsu lub tabeli.

Atrybuty są stosowane do procedur obsługi delegatów i metod, aby zamapować programy obsługi na te obiekty docelowe.

Tworzenie klasy atrybutów

Klasa atrybutów może rozszerzyć klasę SysAttribute bezpośrednio lub rozszerzyć dowolny element potomny klasy SysAttribute . Nie można użyć klasy SysAttribute jako atrybutu, ponieważ jest zadeklarowana jako abstrakcyjna. W poniższym przykładzie przedstawiono deklarację i projekt zwykłej klasy atrybutów, którą można utworzyć.

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.
}

Dekorowanie klasy za pomocą atrybutu

W poniższym przykładzie przedstawiono klasę i metodę, która jest ozdobiona atrybutem PracticeAttribute podanym w poprzednim przykładzie. Jeśli konstruktor atrybutu nie przyjmuje parametrów, nawiasy parametrów są opcjonalne. Dekoracja atrybutu może być [AnotherAttribute] bez nawiasów.

[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.
}

Można pominąć sufiks nazwy atrybutu, jeśli sufiks ma wartość Attribute. Można na przykład użyć [Practice] zamiast [PracticeAttribute] tego w poprzednim przykładzie.

Konstruktory atrybutów

Klasę atrybutów można włączyć do przechowywania dostosowanych metadanych za każdym razem, gdy jest on używany do dekorowania klasy, dzięki czemu jego konstruktor przyjmuje parametry. Parametry konstruktora muszą być literałami typów pierwotnych, takich jak int,wyliczenie lub str. Kompilator nie tworzy wystąpienia klasy atrybutów. Przechowuje nazwę klasy atrybutów oraz wartości literału dla jego konstruktora. W związku z tym, jeśli logika w konstruktorze atrybutu zgłosi wyjątek, wyjątek nie zostanie znaleziony przez dekorowanie klasy z atrybutem . Wyjątek zostanie znaleziony później, gdy proces przyjrzy się klasie, aby zobaczyć atrybut, z który jest ozdobiony. Oznacza to, że atrybut jest konstruowany.

Konwencje nazewnictwa

Wszystkie klasy atrybutów mają sufiks Atrybut w ich nazwie. Sufiks atrybutu jest konwencją nazw, którą zalecamy, ale nie jest to wymaganie systemowe. Możesz określić, czy klasa rozszerza się bezpośrednio z elementu SysAttribute , wybierając klasę w Eksploratorze aplikacji i przeglądając właściwość Extends w oknie Właściwości .

SysObsoleteAttribute

System udostępnia kilka atrybutów, w tym klasę SysObsoleteAttribute . Jednym z zastosowań klasy SysObsoleteAttribute jest powiadomienie kompilatora, że kompilacja powinna zakończyć się niepowodzeniem, jeśli określona metoda jest wywoływana w kodzie źródłowym. Kompilator odrzuca kompilację i wyświetla określony komunikat, który jest przechowywany w tym użyciu atrybutu. Klasę SysObsoleteAttribute można również użyć do powiadamiania kompilatora o zgłaszaniu komunikatów ostrzegawczych zamiast błędów.

Przykład kodu SysObsoleteAttribute

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

Odbicie metadanych

Odbicie służy do znajdowania metadanych atrybutów dołączonych do klasy. Klasy używane do odbicia atrybutu są następujące:

  • Klasa DictClass — dla klas i interfejsów.
  • DictMethod , klasa — w przypadku metod w klasach, interfejsach lub tabelach.

W poprzednich klasach odbicia metody odzwierciedlania metadanych atrybutów są następujące:

  • getAllAttributes , metoda
  • getAttribute, metoda
  • getAttributedClasses , metoda
  • getAttributes , metoda

Uwaga / Notatka

Nie ma mechanizmu wyświetlania listy wszystkich metod lub klas, które są ozdobione określonym atrybutem z kodu X++. Jednak ze względu na to, że kompilator X++ rejestruje te informacje w bazie danych odwołań krzyżowych, informacje te można stamtąd wydobyć.

Przykład kodu odbicia metadanych

Klasa DictMethod służy do znajdowania wartości metadanych atrybutu, który jest dekoracją metody. Poniższy przykład kodu używa klasy SysEntryPointAttribute jako atrybutu. Akceptuje ona wartości parametrów dla nazwy metody oraz nazwę klasy, która zawiera metodę. Metoda parmChecked jest konkretna dla klasy SysEntryPointAttribute i nie jest dziedziczona z klasy bazowej SysAttribute. Każda klasa atrybutów może mieć własną nazwę metody dla metadanych.

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");
}
**************/