Korištenje okvira SysExtension za otkrivanje koju podklasu instancirati u Dynamics AX 2012
Objavljeno: 16. veljače 2025. u 00:28:19 UTC
Zadnje ažuriranje: 12. siječnja 2026. u 08:43:43 UTC
Ovaj članak opisuje kako koristiti malo poznati SysExtension okvir u sustavima Dynamics AX 2012 i Dynamics 365 for Operations za instanciranje podklasa na temelju dekoracija atributa, što omogućuje lako proširiv dizajn hijerarhije klasa obrade.
Using the SysExtension Framework to Find Out Which Subclass to Instantiate in Dynamics AX 2012
Informacije u ovom postu temelje se na Dynamics AX 2012 R3. Mogu, ali i ne moraju biti važeće za druge verzije. (Ažuriranje: Mogu potvrditi da su informacije u ovom članku važeće i za Dynamics 365 for Operations)
Prilikom implementacije klasa obrade u Dynamics AX-u, često se suočavate sa stvaranjem hijerarhije klasa u kojoj svaka podklasa odgovara vrijednosti nabrajanja ili ima neku drugu povezanost podataka. Klasičan dizajn je tada imati metodu konstrukta u nadklasi, koja ima prekidač koji određuje koju klasu instancirati na temelju ulaza.
U principu, ovo dobro funkcionira, ali ako imate mnogo različitih mogućih ulaza (mnogo elemenata u nabrojavanju ili je možda ulaz kombinacija nekoliko različitih vrijednosti), održavanje može postati zamorno i sklono greškama, a dizajn uvijek ima nedostatak da ćete morati modificirati navedenu metodu konstruiranja ako ikada dodate novu podklasu ili napravite promjene u tome koja se podklasa treba koristiti na temelju kojeg ulaza.
Srećom, postoji puno elegantniji, ali nažalost i puno manje poznat način da se to učini, naime korištenjem SysExtension okvira.
Ovaj okvir koristi atribute koje možete koristiti za ukrašavanje svojih podklasa kako bi sustav mogao odrediti koja se podklasa treba koristiti za rukovanje čime. I dalje će vam trebati metoda konstruiranja, ali ako se pravilno napravi, nikada je nećete morati mijenjati prilikom dodavanja novih podklasa.
Pogledajmo zamišljeni primjer i recimo da ćete implementirati hijerarhiju koja obavlja neku vrstu obrade na temelju tablice InventTrans. Koja će se obrada izvršiti ovisi o StatusReceipt i StatusIssue zapisa, kao i o tome jesu li zapisi povezani s SalesLine, PurchLine ili nijednim. Već sada gledate mnogo različitih kombinacija.
Recimo da znate da za sada trebate obraditi samo nekoliko kombinacija, ali također znate da će se od vas s vremenom tražiti da budete u stanju obraditi sve više i više kombinacija.
Recimo da je relativno jednostavno i da za sada trebate obrađivati samo zapise povezane s SalesLine sa StatusIssue od ReservPhysical ili ReservOrdered, sve ostale kombinacije za sada možete zanemariti, ali budući da znate da ćete ih morati obraditi kasnije, htjet ćete dizajnirati svoj kod na način koji ga čini lako proširivim.
Vaša hijerarhija za sada može izgledati ovako:
- MojProcesorMojProcesor_ProdajaMojProcesor_Prodajna_RezervaNaručenoMojaProcesor_Prodajna_RezervaFizička
Sada biste mogli lako implementirati metodu u nadklasi koja instancira podklasu na temelju ModuleInventPurchSales i nabrajanja StatusIssue. Ali tada ćete morati mijenjati nadklasu svaki put kada dodate podklasu, a to zapravo nije ideja nasljeđivanja u objektno orijentiranom programiranju. Uostalom, ne morate mijenjati RunBaseBatch ili SysOperationServiceBase svaki put kada dodate novi batch zadatak.
Umjesto toga, možete koristiti SysExtension framework. To će zahtijevati dodavanje još jedne klase koja treba proširiti SysAttribute. Ova klasa će se koristiti kao atribut kojim možete ukrasiti svoje klase za obradu.
Ova klasa je vrlo slična načinu na koji biste napravili klasu ugovora o podacima za implementaciju SysOperation, po tome što će imati neke podatkovne članove i parm metode za dobivanje i postavljanje tih vrijednosti.
U našem slučaju, ClassDeclaration može izgledati ovako:
{
ModuleInventPurchSales module;
StatusIssue statusIssue;
StatusReceipt statusReceipt
}
Morate napraviti metodu new() za instanciranje svih podatkovnih članova. Ako želite, možete nekima ili svima njima dati zadane vrijednosti, ali ja to nisam učinio.
StatusIssue _statusIssue,
StatusReceipt _statusReceipt)
{
;
super();
module = _module;
statusIssue = _statusIssue;
statusReceipt = _statusReceipt;
}
Također biste trebali implementirati parm metodu za svaki podatkovni član, ali sam ih ovdje izostavio jer sam siguran da znate kako to učiniti - inače, smatrajmo to vježbom ;-)
Sada možete koristiti svoju klasu atributa za ukrašavanje svake od vaših klasa obrade. Na primjer, deklaracije klasa mogle bi izgledati ovako:
StatusIssue::None,
StatusReceipt::None)]
class MyProcessor_Sales extends MyProcessor
{
}
[MyProcessorSystemAttribute(ModuleInventPurchSales::Sales,
StatusIssue::ReservOrdered,
StatusReceipt::None)]
class MyProcessor_Sales_ReservOrdered extends MyProcessor_Sales
{
}
[MyProcessorSystemAttribute(ModuleInventPurchSales::Sales,
StatusIssue::ReservPhysical,
StatusReceipt::None)]
class MyProcessor_Sales_ReservPhysical extends MyProcessor_Sales
{
}
Naravno, svoje klase možete imenovati kako god želite, važno je da svoje klase ukrasite atributima koji odgovaraju vrsti obrade koju obavljaju. (Ali imajte na umu da postoje konvencije imenovanja za hijerarhije klasa u Dynamics AX-u i uvijek je dobra ideja slijediti ih, ako je moguće).
Sada kada ste uredili svoje klase kako biste identificirali koju vrstu obrade svaka od njih obavlja, možete iskoristiti SysExtension framework za instanciranje objekata podklasa prema potrebi.
U vašoj nadklasi (MyProcessor) možete dodati metodu konstruiranja poput ove:
StatusIssue _statusIssue,
StatusReceipt _statusReceipt)
{
MyProcessor ret;
MyProcessorSystemAttribute attribute;
;
attribute = new MyProcessorSystemAttribute( _module,
_statusIssue,
_statusReceipt);
ret = SysExtensionAppClassFactory::getClassFromSysAttribute(classStr(MyProcessor), attribute);
if (!ret)
{
// no class found
// here you could throw an error, instantiate a default
// processor instead, or just do nothing, up to you
}
return ret;
}
Zaista zanimljiv dio - i zapravo cilj (oprostite na igri riječi) cijelog ovog posta - je metoda getClassFromSysAttribute() u klasi SysExtensionAppClassFactory. Ova metoda prihvaća naziv nadklase hijerarhije (i ta nadklasa ne mora biti na vrhu hijerarhije; to jednostavno znači da će samo klase koje proširuju tu klasu biti prihvatljive) i objekt atributa.
Zatim vraća objekt klase koja proširuje navedenu nadklasu i ukrašena je odgovarajućim atributom.
Očito možete dodati onoliko daljnje validacije ili logike metodi konstruiranja koliko želite, ali važna stvar ovdje je da nakon implementacije, više nikada ne biste trebali morati mijenjati ovu metodu. Možete dodati podklase hijerarhiji i sve dok se pobrinete da ih pravilno ukrasite, metoda konstruiranja će ih pronaći čak i ako nisu postojale kada je napisana.
Što je s performansama? Iskreno, nisam pokušao napraviti benchmark, ali imam osjećaj da ovo vjerojatno ima lošije performanse od klasičnog dizajna switch naredbi. Međutim, s obzirom na to da je daleko najviše problema s performansama u Dynamics AX-u uzrokovano pristupom bazi podataka, ne bih se previše brinuo oko toga.
Naravno, ako implementirate nešto što će zahtijevati brzo stvaranje tisuća objekata, možda biste trebali dalje istražiti, ali u klasičnim slučajevima kada samo instancirate jedan objekt za dugotrajnu obradu, sumnjam da će to biti važno. Također, s obzirom na moj savjet za rješavanje problema (sljedeći odlomak), čini se da se SysExtension framework oslanja na predmemoriranje, pa u pokrenutom sustavu sumnjam da ima značajan pad performansi.
Rješavanje problema: Ako metoda konstruiranja ne pronađe vaše podklase iako ste sigurni da su ispravno uređene, problem bi mogao biti u predmemoriranju. Pokušajte izbrisati predmemoriju i na klijentu i na poslužitelju. Ne bi trebalo biti potrebno ponovno pokrenuti AOS, ali to može biti krajnja opcija.
Dodatno čitanje
Ako vam se svidio ovaj post, možda će vam se svidjeti i ovi prijedlozi:
- Identificiranje klase dokumenta i upita za AIF uslugu u sustavu Dynamics AX 2012
- Pogreška "Nije definirana klasa metapodataka za podatkovni ugovorni objekt" u programu Dynamics AX 2012
- Oblikovanje niza s makronaredbom i strFmt u Dynamics AX 2012
