Classes de atributo de X++

Este artigo descreve o uso de atributos em X++.

Um atributo é uma classe nonabstract que estende (herda de) a classe SysAttribute . Os atributos representam ou armazenam metadados sobre tipos e métodos. Você pode anexar um atributo a uma classe, um campo de classe, um método de classe, uma interface ou uma tabela.

Aplique atributos aos manipuladores de delegados e métodos para mapear os manipuladores para esses destinos.

Criando uma classe de atributo

Uma classe de atributo pode estender a classe SysAttribute diretamente ou pode estender qualquer descendente da classe SysAttribute . Você não pode usar a classe SysAttribute como um atributo porque ela é declarada abstrata. O exemplo a seguir mostra a declaração e o design de uma classe de atributo comum que você pode criar.

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

Decorando uma classe com um atributo

O exemplo a seguir mostra uma classe e um método decorados com o PracticeAttribute dado no exemplo anterior. Se o construtor do atributo não tiver parâmetros, os parênteses dos parâmetros serão opcionais. A decoração de atributo pode ser [AnotherAttribute] sem parênteses.

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

Você pode omitir o sufixo do nome do atributo se o sufixo for Attribute. Por exemplo, você pode usar [Practice] no [PracticeAttribute] exemplo anterior.

Attribute constructors

Você pode habilitar sua classe de atributo para armazenar metadados personalizados sempre que decorar uma classe, fazendo com que seu construtor use parâmetros. Os parâmetros para o construtor devem ser literais dos tipos primitivos, como int,enum oustr. O compilador não constrói uma instância da classe de atributo. Ele armazena o nome da classe de atributo, além dos valores literais para seu construtor. Portanto, se a lógica em um construtor de atributo gerar uma exceção, decorar uma classe com o atributo não causará a exceção. A exceção é encontrada posteriormente quando um processo examina uma classe para ver o atributo com o qual ela é decorada. Esse processo é quando o atributo é construído.

Naming conventions

Todas as classes de atributo têm o atributo de sufixo em seu nome. O sufixo Attribute é a convenção de nome que a Microsoft recomenda, mas não é um requisito do sistema. Você pode determinar se uma classe se estende diretamente de SysAttribute selecionando a classe no Gerenciador de Aplicativos e revisando a propriedade Extends na janela Propriedades .

SysObsoleteAttribute

O sistema fornece vários atributos, incluindo a classe SysObsoleteAttribute . Um uso da classe SysObsoleteAttribute é notificar o compilador de que o compilador deve falhar se um método específico for chamado no código-fonte. O compilador rejeita o compilador e exibe a mensagem específica armazenada neste uso do atributo. A classe SysObsoleteAttribute também pode ser usada para notificar o compilador para emitir mensagens de aviso em vez de erros.

Exemplo de código SysObsoleteAttribute

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

Metadata reflection

Você usa a reflexão para localizar os metadados de atributo anexados a uma classe. As classes a serem usadas para reflexão de atributo são as seguintes:

  • Classe DictClass – Para classes e interfaces.
  • Classe DictMethod – Para métodos em classes, interfaces ou tabelas.

Nas classes de reflexão anteriores, os métodos para refletir sobre metadados de atributo são os seguintes:

  • getAllAttributes method
  • getAttribute method
  • getAttributedClasses method
  • getAttributes method

Note

Não há nenhum mecanismo para listar todos os métodos ou classes adornados com um atributo específico do código X++. No entanto, como o compilador X++ registra essas informações no banco de dados de referência cruzada, você pode extrair essas informações nela.

Exemplo de código de reflexão de metadados

Use a classe DictMethod para localizar o valor de metadados de um atributo que decora um método. O exemplo de código a seguir usa a classe SysEntryPointAttribute como o atributo. Ele aceita seus valores de parâmetro para o nome do método e para o nome da classe que contém o método. O método parmChecked é particular para a classe SysEntryPointAttribute e não é herdado de sua classe base SysAttribute. Cada classe de atributo pode ter seu próprio nome de método para seus metadados.

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