RTTI a nové RTTI v Delphi 2010

vložil Radek Červinka 29. prosince 2009 02:07

V nových Delphi 2010 bylo konečně vylepšeno RTTI (Run Time Type Information - tj. informace o typech získané za běhu).

Jen ve zkratce dřívější stav: pokud při deklaraci třídy uvedete published, budou členy v této skupině mít sice viditelnost jako public, ale kompilátor k nim navíc přigeneruje speciální RTTI informace.

Tyto informace používá Delphi např. pro ukládání a načítání DFM souborů, zobrazování dat v Object Inspectoru a další. Kromě toho se pomocí několika metod dají používat i ve Vašem kódu (např. ClassInfo, GetTypeData, GetPropInfo, GetPropList, GetEnumName, GetEnumValue …).

    1uses Typinfo;
    2{$R *.DFM}
    3
    4procedure TForm1.FormCreate(Sender: TObject);
    5var
    6  Count, Loop: Integer;
    7  List: TPropList;
    8begin
    9  Count := GetPropList(TypeInfo(TForm1), tkAny, @List);
   10  Listbox1.Items.BeginUpdate;
   11  for Loop := 0 to Pred(Count) do
   12    Listbox1.Items.Add(List[Loop]^.Name);
   13  Listbox1.Items.EndUpdate;
   14
   15end;

nebo

    1ShowMessage(GetEnumName(TypeInfo(TFormBorderStyle), Ord(BorderStyle)));

Podrobněji o originálním RTTI zde spolu s pěknými příklady.

RTTI a Delphi 2010

Kromě původních RTTI je v Delphi 2010 přidána možnost Atributů jako má třeba C#. Všechny atributy jsou následníkem TCustomAttribute a mohou tudíž mít metody, property atd. (viz. třída MyAttribute v příkladu).

Příklad ukazuje jednoduché dotazování RTTI (nezapomenout že veškerá podpora je v rtti.pas). V reálném případě by TMyClass pak byl objekt a v proceduře Test by se pracovalo i s tímto objektem (resp. jeho daty). Cílem by bylo uložení dat objektu TMyClass za pomoci RTTI do datového úložiště.

Pro zajímavost dle komentáře autora implementace v Delphi (Barry Kelly), je TRttiContext record zapouzdřující interface a je vytvořen při přístupu a uvolněn mimo viditelnost, tj. Create a Free nejsou třeba.

Použití může být již uvedené ukládání a načítání objektů do DB nebo třeba kdykoliv, kdy se vyplatí napsat obecný přístup pro práci s daty, které mají něco společného.

    1program Project1;
    2
    3{$APPTYPE CONSOLE}
    4
    5uses
    6  SysUtils, Rtti;
    7
    8type
    9  // definice atrubutu
   10  MyAttribute = class(TCustomAttribute)
   11  private
   12    FFieldName: string;
   13    FSize: Integer;
   14  public
   15    constructor Create(const sFieldName : string; iSize : Integer);
   16    property FieldName : string read FFieldName write FFieldName;
   17    property Size : Integer read FSize write FSize;
   18  end;
   19
   20  // nase trida
   21  TMyClass = class
   22  private
   23    FFirstName:string;
   24    FSurname: string;
   25  public
   26    [MyAttribute('dcFirstName', 50)]        // v podstate volaní constructoru MyAttribute.Create
   27    property FirstName:string read FFirstName write FFirstName;
   28    [MyAttribute('dcSurnName', 30)]
   29    property SurName: string read FSurname write FSurname;
   30  end;
   31
   32
   33constructor MyAttribute.Create(const sFieldName: string; iSize: Integer);
   34begin
   35  FSize := iSize;
   36  FFieldName := sFieldName;
   37end;
   38
   39// zde se pracuje s RTTI
   40procedure Test;
   41var
   42  ctx : TRttiContext;
   43  t : TRttiType;
   44  m : TRttiProperty;
   45  a : TCustomAttribute;
   46begin
   47
   48  ctx := TRttiContext.Create;
   49  try
   50    t := ctx.GetType(TMyClass);
   51    for m in t.GetProperties do 
   52      for a in m.GetAttributes do
   53        if a is MyAttribute then // ať se nám tam neplete nic co není naše
   54          writeln(Format('Property = %s; Attribute = %s, FieldName = %s, Size = %d',
   55                                    [m.Name, a.ClassName, MyAttribute(a).FieldName,
   56                                     MyAttribute(a).Size]));
   57  finally
   58    ctx.Free;
   59  end;
   60end;
   61
   62begin
   63  Test;
   64end.

Výsledek je pak:

Property = FirstName; Attribute = MyAttribute, FieldName = dcFirstName, Size = 50
Property = SurName; Attribute = MyAttribute, FieldName = dcSurnName, Size = 30

Samozřejmě každá sranda něco stojí a proto jsou EXE díky RTTI trošku větší (ale ne zas tak moc). Pokud použijete {$WEAKLINKRTTI ON} nebo dcc32 –weaklinkrtti popř. na začátku každého unitu (lépe přes include)

{$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}

tak výsledná velikost EXE bude menší (ale zase nebudete moci použít nové RTTI).

A poslední poznámka: TRttiMethod umožňuje volání metod objektu za běhu:

    1TRttiMethod = class(TRttiMember)
    2 //…
    3  function Invoke(Instance: TObject; const Args: array of TValue): TValue; overload;
    4  function Invoke(Instance: TClass; const Args: array of TValue): TValue; overload;
    5  function Invoke(Instance: TValue; const Args: array of TValue): TValue; overload;
    6  function GetParameters: TArray<TRttiParameter>; virtual; abstract;
    7  function ToString: string; override;
    8  property ReturnType: TRttiType read GetReturnType;
    9end;


Nabízíme Delphi školení na různá témata, primárně ve Vaší firmě.

Tagy: , , , ,

Jazyk | Recenze

Komentování ukončeno

Naše nabídka

Partial English version.

MVP
Ing. Radek Červinka - Embarcadero MVP
profil na linkedin, Twitter:@delphicz

Nabízím placené poradenství a konzultace v oblasti programování a vývoje SW.
Dále nabízíme i vývoj speciálního software na zakázku.

Neváhejte nás kontaktovat (i ohledně reklamy nebo burzy práce).

Pokud chcete podpořit tento server libovolnou částkou, můžete použít PayPal. Moc děkuji.

Delphi Certified Developer

O Delphi.cz

Delphi je jediný moderní RAD nástroj podporující tvorbu nativních aplikací pro platformu Win32, Win64 , Mac OSX a na iPhone a Android (s výhledem na další platformy díky FireMonkey) na současném trhu (včetně Windows 8.1).

V současnosti je světová komunita přes dva miliónů vývojářů.

Delphi.cz je nezávislý portál pro uživatele Delphi. Portál není koncipován pro úplné začátečníky, i když i ti se zde nebudou nudit, ale spíše na programátory, kteří již něco znají a chtějí své znalosti dále rozvíjet a sledovat novinky.

Anketa

Poslední komentáře

Comment RSS