Nota
L'accesso a questa pagina richiede l'autorizzazione. Puoi provare ad accedere o a cambiare directory.
L'accesso a questa pagina richiede l'autorizzazione. Puoi provare a cambiare directory.
Nota
I gruppi di interesse della community sono ora passati da Yammer a Microsoft Viva Engage. Per entrare a far parte di una community Viva Engage e partecipare alle discussioni più recenti, compila il modulo Richiedi l'accesso alla community Viva Engage per Finance and Operations e scegli la community a cui vuoi unirti.
In questo articolo viene descritto l'uso degli attributi in X++.
Un attributo è una classe non astratta che estende (eredita da) la classe SysAttribute . Gli attributi rappresentano o archiviano i metadati relativi a tipi e metodi. Un attributo può essere associato a una classe, a un campo di classe, a un metodo di classe, a un'interfaccia o a una tabella.
Gli attributi vengono applicati ai gestori di delegati e metodi per eseguire il mapping dei gestori a tali destinazioni.
Creazione di una classe di attributi
Una classe di attributi può estendere direttamente la classe SysAttribute oppure può estendere qualsiasi discendente della classe SysAttribute . La classe SysAttribute non può essere utilizzata come attributo perché è dichiarata astratta. Nell'esempio seguente vengono illustrate la dichiarazione e la progettazione di una classe di attributi ordinaria che è possibile creare.
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.
}
Decorare una classe con un attributo
Nell'esempio seguente vengono illustrati una classe e un metodo decorati con l'oggetto PracticeAttribute fornito nell'esempio precedente. Se il costruttore dell'attributo non accetta parametri, le parentesi per i parametri sono facoltative. La decorazione dell'attributo potrebbe essere [AnotherAttribute] senza parentesi.
[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.
}
È possibile omettere il suffisso del nome dell'attributo se il suffisso è Attribute. Ad esempio, è possibile utilizzare [Practice] invece [PracticeAttribute] nell'esempio precedente.
Costruttori di attributi
È possibile abilitare la classe di attributi per archiviare metadati personalizzati ogni volta che viene utilizzata per decorare una classe, facendo in modo che il costruttore accetti i parametri. I parametri per il costruttore devono essere valori letterali dei tipi primitivi, ad esempio int,enum o str. Il compilatore non costruisce un'istanza della classe dell'attributo. Memorizza il nome della classe di attributi, oltre ai valori letterali per il relativo costruttore. Pertanto, se la logica in un costruttore di attributi genera un'eccezione, l'eccezione non viene trovata decorando una classe con l'attributo. L'eccezione viene trovata in un secondo momento, quando un processo esamina una classe per vedere l'attributo con cui è decorata. Questo è il momento in cui l'attributo viene costruito.
Convenzioni di denominazione
Tutte le classi di attributi hanno il suffisso Attribute nel nome. Il suffisso Attribute è la convenzione del nome consigliata, ma non è un requisito di sistema. È possibile determinare se una classe si estende direttamente da SysAttribute selezionando la classe in Esplora applicazioni ed esaminando la proprietà Extends nella finestra Proprietà .
Attributo SysObsolete
Il sistema fornisce diversi attributi, tra cui la classe SysObsoleteAttribute . Un utilizzo della classe SysObsoleteAttribute consiste nel notificare al compilatore che la compilazione deve avere esito negativo se viene chiamato un determinato metodo nel codice sorgente. Il compilatore rifiuta la compilazione e visualizza il messaggio specifico archiviato in questo utilizzo dell'attributo. La classe SysObsoleteAttribute può essere utilizzata anche per notificare al compilatore l'emissione di messaggi di avviso anziché di errori.
Esempio di codice SysObsoleteAttribute
[SysObsoleteAttribute("The Automobile class might have faster performance.", false)]
class Bicycle
{
// Members of the Bicycle class go here.
}
Riflessione dei metadati
La reflection viene utilizzata per trovare i metadati dell'attributo associati a una classe. Le classi da utilizzare per la reflection degli attributi sono le seguenti:
- Classe DictClass – Per classi e interfacce.
- Classe DictMethod : per i metodi su classi, interfacce o tabelle.
Nelle classi di reflection precedenti, i metodi per riflettere sui metadati degli attributi sono i seguenti:
- Metodo getAllAttributes
- Metodo getAttribute
- Metodo getAttributedClasses
- Metodo getAttributes
Nota
Non esiste alcun meccanismo per elencare tutti i metodi o le classi che sono adornati con un particolare attributo del codice X++. Tuttavia, poiché il compilatore X++ registra queste informazioni nel database dei riferimenti incrociati, le informazioni possono essere estratte da lì.
Esempio di codice di reflection dei metadati
La classe DictMethod viene utilizzata per trovare il valore dei metadati di un attributo che costituisce una decorazione in un metodo. Nell'esempio di codice riportato di seguito viene utilizzata la classe SysEntryPointAttribute come attributo. Accetta i valori dei parametri per il nome del metodo e per il nome della classe che contiene il metodo. Il metodo parmChecked è specifico della classe SysEntryPointAttribute e non viene ereditato dalla relativa classe di base SysAttribute. Ogni classe di attributo può avere il proprio nome di metodo per i metadati.
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");
}
**************/