středa 28. října 2009
Nová kniha o Dynamics AX
Další kniha o programování v Dynamics AX je na cestě, konkrétně jde o Microsoft Dynamics AX 2009 Programming: Getting Started. Předpokládané vydání v prosinci, ale již nyní je možné objednávat.
Bohužel nevím o obsahu nic víc, než co najdete na uvedeném odkazu.
sobota 24. října 2009
Generování přístupových metod
Vytváření přístupových metod (tzn. metod zpřístupňujících neveřejné členy tříd) je velmi častá činnost. Členské proměnné tříd totiž nejsou přímo přístupné pro čtění či zápis a je proto nezbytné vytvořit metody, která vrátí či nastaví hodnotu dané proměnné.
Díky tomuto řešení lze například zcela odstranit proměnnou a nahradit ji nějakým výpočtem, aniž by bylo třeba provádět změny mimo danou třídu.
Přístupové metody mají obvykle prefix get (metoda pro čtení) nebo set (pro zápis), v AX se typicky kombinují do jediné metody s prefixem parm, která slučuje obě funkce. (V AX se používá několik přístupů - get metody jsou většinou zcela bez prefixu, někdo naopak propaguje používání prefixu parm i pro metody jen pro čtení či jen pro zápis atd.)
Šablona parm metody
V Dynamics AX si lze psaní přístupových metod zjednodušit pomocí šablon metod. V editoru otevřte Scripts > template > method > parm, případně použijte sekvenci zkratek "Alt+R" (Alt+M ve starších verzích) "S" "T" "M" "P". Do dialogu zadáte typ a název proměnné a po potvrzení bude vygenerovaný kód vložen na pozici kurzoru.
Stále to ale není "ono". Je třeba vytvořit metodu, vymazat její obsah, ale zejména vědět typ a název proměnné. S jednou metodou se člověk vypořádá snadno, ale má-li jich vytvářet několik desítek, rázem vidí tento problém v jiném světle. Musí hledat deklarace požadovaných proměnných, vytvářet metody, kopírovat typy a názvy a tak dále. To je neproduktvní a stereotypní činnost, která volá po automatizaci.
Generátor
Proto jsem vytvořil generátor přístupových metod, který umí o něco víc. Konkrétně:
Po potvrzení zadání se zobrazí infolog s výsledky generování. Z něj lze dvojklikem otevřít metodu v editoru. Existující metody nejsou přepsány.
Pár poznámek k implementaci
- zobrazí členské proměnné dané třídy (formuláře, datasetu apod.) včetně zděděných a umožní vybrat, pro které budou vytvořeny přístupové metody
- tento seznam je možné filtrovat
- umožňuje nastavit, zda vygenerovaná metoda bude určena pro čtení, zápis nebo obojí
- umožňuje změnit vygenerovaný název proměnné a parametru

- Vývoj i testování generátoru proběhly v AX2009.
- Potřebujete-li změnit vytváření výchozích názvů metod a parametrů, změňte metody initMethodName() a initParameterName() na tabulce TmpDevAccessorMethod.
- Pokud v dialogu měníte hodnoty checkboxů Read a Write, mění se i prefix v názvu metody. Jakmile však zadáte svůj název, změny Read/Write na něj nemají vliv.
- Vygenerované metody nepoužívají prmIsDefault(), což může být v některých případech problém. Bohužel, v tuto chvíli vám nezbývá než modifikovat vygenerovanou metodu ručně. Mám tuto vlastnost v "Nice to have". :-)
- Přidat do menu
- Určit, u kterých elementů bude tato volba dostupná (
case menuitemActionStr(DevAccessorMethodsGenerator):
if (this.selectionCount() == 1
&& !firstNode.AOTIsOld()
&& DevAccessorMethodsGenerator::isSupportedTreeNode(firstNode))
{
return 1;
}
return 0;
Zpětná vazba
Připomínky jsou vítané, hlášení chyb vyžadované. :-)
Download
Generátor přístupových metod (AX2009)
neděle 11. října 2009
Otevírání formulářů v hlavním okně
Na AxForu jsem narazil na nápad změnit chování AX2009 tak, aby se formuláře otevíraly vždy v hlavním okně (originální post) a ne v oknech samostatných (tedy aby se chovaly stejně jako v dřívějších verzích). Já jsem si to ještě rozšířil o ListPages a dostal jsem tak všechny formuláře pod kontrolu Tabaxu.
Toto uspořádání mi vyhovuje daleko více než to standardní. Potřebuji-li pracovat s příliš mnoha okny, otevřu si další workspace a v každém workspace pak udržuji související okna. Nemusím tak řešit chaos na taskbaru pokud například pracuji ve více prostředích a společnostech.
Programová úprava je jednoduchá - do SysSetupForm.init() před super() jsem přidal:
if (this.form().design().windowType() == FormWindowType::Standard
|| this.form().design().windowType() == FormWindowType::ListPage)
{
this.form().design().windowType(FormWindowType::Workspace);
}
Prosté a efektivní. Tak to má být. :-)
sobota 10. října 2009
Překlad X++ do MSIL
Před pár dny jsem konečně našel čas a podíval se na video Peter Villadsen and Gustavo Plancarte: X++ to MSIL z Channel9. A musím říct, že opravdu stojí za zhlédnutí.
V krátkosti tam lidé z X++ teamu popisují, proč a jak vytvořili překlad z mezijazyka AX do MSIL (Microsoft Intermediate Language - do něj jsou překládány všechny .NET jazyky). Dále také ukazují debugging X++ v prostředí Visual Studia a na závěr připouští možnost rychlého opuštění X++. A upřímně, ty možnosti jsou natolik lákavé, že to podle mého názoru sotva může v budoucnu dopadnout jinak. Špičkové vývojové prostředí, mj. také jednotné prostředí (když se ve VS už vyvíjí EP, reporty, workflow…), pohodlná integrace, testovací nástroje, plné využití TFS…
Vůbec jsem netušil, že se do tohoto překladače Microsoft už pustil, natož že ho má hotový. Udělali mi velkou radost. :-)
pátek 9. října 2009
Zobrazení názvu reportu
Na úvod malé vysvětlení, proč jsem se v poslední době poněkud odmlčel. Absolvoval jsem totiž stěhování a až dnes mě připojili k internetu, no a na novém projektu se také nenudím :-). Nicméně na pár zajímavých věcí jsem narazil, snad z toho dám něco v nejbližších dnech do zveřejnitelné podoby.
Začnu tou nejčerstvější věcí. Dnes jsme řešili, jak nesnáze získat AOT jméno reportu (tiskové sestavy) vytištěné na obrazovku. Zkrátka máte na obrazovce report, chcete jej editovat/prozkoumat implementaci a nevíte, jak ho vlastně najít v AOT. Možnosti samozřejmě existují, ale nejsou příliš pohodlné. (Tedy pokud o nějaké víte, dejte vedět!)
Já jsem zvolil řešení, které sice vyžaduje programovou úpravu, ale jeden řádek není zas tolik. ;-) Do titulku okna reportu jsem přidal jméno reportu - stačí k tomu drobná úprava metody createReportViewer() ve třídě ClassFactory:
public ReportViewer createReportViewer(
PrintJobHeader _jobsCursor,
PrintJobPages _pagesCursor,
ReportRun _reportRun = null)
{
ReportViewer ret;
ret = super(_jobsCursor, _pagesCursor, _reportRun);
ret.description(strFmt("%1 (%2)", ret.description(), _reportRun.name()));
return ret;
}
A nezbytná ukázka výsledku:

Přihlásit se k odběru:
Příspěvky (Atom)