Overview

Custom Attributes

Showcases declarative programming and metadata-driven logic. This example demonstrates how to define custom attribute classes inheriting from 'TCustomAttribute', annotate other types with these attributes, and use 'RTTIRawAttributes' to programmatically discover and act upon this metadata at runtime for tasks like mapping classes to database tables.

Source Code

<?pas
// Define custom attributes
type
  TableAttribute = class(TCustomAttribute)
    FName: String;
    constructor Create(name: String);
    begin
      FName := name;
    end;
  end;

// Annotated entity classes
type
  [TableAttribute('users')]
  TUser = class
    ID: Integer;
    Name: String;
  end;

type
  [TableAttribute('orders')]
  TOrder = class
    OrderID: Integer;
  end;

// Discover attributes at runtime
PrintLn('Entity Metadata:');

var attrs := RTTIRawAttributes;
for var i := 0 to attrs.Length - 1 do begin
  // attrs[i].T is the type info target
  // attrs[i].A is the attribute instance
  
  if attrs[i].T = TypeOf(TUser) then begin
    if attrs[i].A is TableAttribute then
      PrintLn('TUser -> Table: ' + TableAttribute(attrs[i].A).FName);
  end;

  if attrs[i].T = TypeOf(TOrder) then begin
    if attrs[i].A is TableAttribute then
      PrintLn('TOrder -> Table: ' + TableAttribute(attrs[i].A).FName);
  end;
end;

// Simple TypeOf usage
var info := TypeOf(TUser);
PrintLn('Class name from RTTI: ' + info.Name);
?>

Result

Entity Metadata:
TUser -> Table: users
TOrder -> Table: orders
Class name from RTTI: TUser
On this page