Benutzerdefinierte Attribute deklarieren (RTTI)

Aus Appmethod Topics
Wechseln zu: Navigation, Suche

Nach oben zu Attribute - Index


In diesem Thema werden die grundlegenden Methoden zum Erstellen von benutzerdefinierten Attributen, die korrekten Designentscheidungen für Attributklassen und deren allgemeine Verwendung beschrieben.

Deklarieren eines Attributs

Ein Attribut ist ein einfacher Klassentyp. Um ein eigenes benutzerdefiniertes Attribut zu erstellen, müssen Sie es von der speziellen, vordefinierten Klasse System.TCustomAttribute ableiten:

type
    MyCustomAttribute = class(TCustomAttribute)
    end;

Mit MyCustomAttribute können dann beliebige Typen oder Member eines Typs (wie z. B. Klasse, Record oder Interface) mit Annotationen versehen werden:

type
   [MyCustomAttribute]
   TSpecialInteger = type integer;

   TSomeClass = class
        [MyCustomAttribute]
        procedure Work;
   end;

Beachten Sie, dass die deklarierte Attributklasse nicht als class abstract deklariert werden darf und keine abstrakten Methoden enthalten sollte. Obwohl der Compiler die Verwendung dieser Attribute für die Annotation zulässt, enthält die erzeugte Binärdatei diese Attribute nicht in den ausgegebenen RTTI-Informationen.

Attributnamen mit der Endung "Attribute" werden implizit verkürzt

Angenommen, Sie deklarieren zwei TCustomAttribute-Unterklassen mit demselben Namenspräfix, wovon aber eine das Suffix "Attribute" enthält:

  • MyCustom
  • MyCustomAttribute

Die Klasse mit dem Suffix "Attribute" (MyCustomAttribute) wird immer verwendet, und auf die Klasse mit dem kürzeren Namen (MyCustom) kann nicht zugegriffen werden.

Das folgende Codefragment verdeutlicht dieses Problem. Man könnte annehmen, dass die TCustomAttribute-Unterklasse Test übernommen wird, aber tatsächlich wird aufgrund der impliziten Namensverkürzung TestAttribute übernommen, wenn [Test] oder [TestAttribute] verwendet wird.

type
  // To check ambigious names
  TestAttribute = class(TCustomAttribute)
  end;

  // Becomes unaccessible
  Test = class(TCustomAttribute)
  end;

  [Test] // Resolves to TestAttribute at run time
  TAmbigiousClass = class
  end;

Konstruktoren in Attributen

In der Regel sollen Attribute zusätzliche Informationen enthalten, die zur Laufzeit abgefragt werden können. Damit benutzerdefinierte Informationen für die Attributklasse festgelegt werden können, müssen Sie Konstruktoren dafür deklarieren:

type
    AttributeWithConstructor = class(TCustomAttribute)
    public
        constructor Create(const ASomeText: String);
   end;

Die dann folgendermaßen verwendet werden können:

 type
   [AttributeWithConstructor('Added text value!')]
   TRecord = record
        FField: Integer;
   end;

Die Methodenauflösung wird auch für Attribute angewendet. Das bedeutet, dass Sie überladene Konstruktoren im benutzerdefinierten Attribut definieren können. Deklarieren Sie nur Konstruktoren, die konstante Werte akzeptieren und keine out- oder var-Werte. Das liegt an einer grundlegenden Einschränkung bei der Funktionsweise von Attributen und wird unter Hinweise zu Typen und Membern hinzufügen detailliert erläutert.

Siehe auch