Compartilhar via


Classes de atributo de X++

Observação

Grupos de interesse da comunidade mudaram do Yammer para o Microsoft Viva Engage. Para ingressar em uma comunidade do Viva Engage e participar das discussões mais recentes, preencha o formulário Solicitar acesso às Finanças e Operações viva engage community e escolha a comunidade que você deseja ingressar.

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

Um atributo é uma classe não abstrata que estende (herda de) a classe SysAttribute . Os atributos representam ou armazenam metadados sobre tipos e métodos. Um atributo pode ser anexado a uma classe, um campo de classe, um método de classe, uma interface ou uma tabela.

Os atributos são aplicados 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 . A classe SysAttribute não pode ser usada como um atributo porque é declarada abstrata. O exemplo a seguir mostra a declaração e o design de uma classe de atributo comum que você poderia 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.

Construtores de atributo

Você pode habilitar sua classe de atributo para armazenar metadados personalizados sempre que ele for usado para 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, a exceção não será encontrada decorando uma classe com o atributo. A exceção será encontrada posteriormente quando um processo examinar uma classe para ver o atributo com o qual ela é decorada. É quando o atributo é construído.

Convenções de nomenclatura

Todas as classes de atributo têm o atributo de sufixo em seu nome. O sufixo Attribute é a convenção de nome que recomendamos, 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.
}

Reflexão de metadados

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:

  • Método getAllAttributes
  • Método getAttribute
  • Método getAttributedClasses
  • Método getAttributes

Observação

Não há 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, as informações podem ser extraídas 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ção em 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");
}
**************/