neděle 12. července 2009

Reflexe - úvod

Reflexe (reflection) umožňuje pracovat se strukturou programu samotného. Když například Unit Testing Framework spouští všechny metody začínající "test", využívá k tomu reflexi. Hrátky s reflexí jsou zábavné a zároveň umožní tvořit velmi zobecněná řešení některých problémů, takže ji určitě neignorujte. :-) Obecně bych rozdělil využití reflexe v Axaptě do dvou hlavních oblastí: 1. Analýza aplikace - například:
  • vyhledání tříd implementujících dané rozhraní (Které RunBaseBatch třídy se mění aktuálním releasem?)
  • výpis polí tabulky pro uživatelský výběr (AIF, DEV_SysTableBrowser)
  • generátory kódu (metoda find() na základě primárního indexu)
  • atd.
2. Ovlivnění business logiky - tím míním např.:
  • volání metod na základě dat (Např. volám konkrétní metodu všech tříd, jejichž názvy jsem uložil do tabulky. To mi umožní měnit aplikační logiku dle aktuálních požadavků bez potřeby zásahu do kódu.)
  • provedení určité akce se všemi poli v tabulce, nebo třeba s poli určitého datové typu (validace)
  • atd.
Z funkčního hlediska existují dva přístupy:
  • TreeNode - představuje práci s AOT. Umožňuje procházet AOT, spouštět objekty, vytvářet, exportovat, pracovat s vrstvami atd. Základem je třída TreeNode, resp. její rozšíření SysTreeNode.
  • Dictionary - pracuje jen s datovým slovníkem (EDT, tabulky, třídy; ne třeba formuláře), ale objektům "rozumí" lépe než TreeNode. Pracuje s dědičností, přístupovými modifikátory (např. private), databází atd. Využívá systémové třídy Dict* a aplikační třídy SysDict*, v kterých jsou mnohá užitečná rozšíření.
Ještě se sluší poznamenat, že některé úkoly lze realizovat i jinak a mnohdy i efektivněji. Napadají mě třeba:
  • křížové reference (pokud jsou aktuální, samozřejmě)
  • UtilElements a další systémové tabulky
  • polymorfismus (jinak řečeno - řešení vhodným objektovým návrhem)
Na závěr dva jednoduché příklady, složitější aplikace si schovám na jindy. Ukázka 1 - Dictionary
Dictionary dictionary = new Dictionary();
DictClass dictClass;
ClassId classId;
;

classId = dictionary.classNext(0);

while (classId)
{
    dictClass = dictionary.classObject(classId);
    info(strFmt(
        "Třída %1 - instančních metod: %2",
        dictClass.name(),
        dictClass.objectMethodCnt()));
    classId = dictionary.classNext(classId);
}
Ukázka 2 - TreeNode
TreeNode formsNode = TreeNode::findNode(@'\Forms\'); //cesta v AOT
TreeNodeIterator iterator;
TreeNode formNode;
;

iterator = formsNode.AOTiterator();
formNode = iterator.next();

while (formNode)
{
     info(strFmt(
         "Formulář %1 - datových zdrojů: %2",
         formNode.AOTname(),
         formNode.AOTfindChild('Data Sources').AOTchildNodeCount()));
    formNode = iterator.next();
}

Žádné komentáře:

Okomentovat