Korišćenje okvira SisEktension da biste saznali koju podklasu treba instancirati u Dinamics AKS KSNUMKS
Objavio: 19. mart 2025. 21:25:41 UTC
Ovaj članak opisuje kako koristiti malo poznati okvir SisEktension u Dinamics AKS 2012 i Dinamics 365 for Operations za instanciranje podklasa na osnovu ukrasa atributa, omogućavajući lako proširiv dizajn hijerarhije klase obrade.
Using the SysExtension Framework to Find Out Which Subclass to Instantiate in Dynamics AX 2012
Informacije u ovom postu su zasnovane na Dinamics AKS 2012 R3. Može ili ne mora da važi za druge verzije. (Ažuriranje: Mogu da potvrdim da informacije u ovom članku važe i za Dinamics KSNUMKS for Operations)
Kada implementirate klase obrade u Dinamics AKS-u, često se suočavate sa kreiranjem hijerarhije klasa u kojoj svaka podklasa odgovara vrednosti enuma ili ima neku drugu vezu podataka. Klasičan dizajn je da se u super klasi napravi metoda, koja ima prekidač koji određuje koja klasa će instancirati na osnovu ulaza.
Ovo dobro funkcioniše u principu, ali ako imate mnogo različitih mogućih ulaza (mnogi elementi u enumu ili možda ulaz je kombinacija nekoliko različitih vrednosti), može postati dosadan i sklon greškama za održavanje i dizajn uvek ima nedostatak da ćete morati da modifikujete pomenuti metod konstrukcije ako ikada dodate novu podklasu ili napravite izmene u kojoj podklasi treba da se koristi na osnovu kog ulaza.
Srećom, postoji mnogo elegantniji, ali nažalost i mnogo manje poznat, način da se to uradi, naime upotrebom SisEktension okvira.
Ovaj okvir koristi atribute koje možete koristiti za ukrašavanje vaših podklasa kako bi sistem mogao da shvati koja podklasa treba da se koristi za rukovanje šta. I dalje će vam biti potreban metod konstrukcije, ali ako se to uradi ispravno, nikada nećete morati da ga menjate prilikom dodavanja novih podklasa.
Pogledajmo imaginarni primer i recimo da ćete implementirati hijerarhiju koja radi neku vrstu obrade zasnovane na InventTrans tabeli. Koja obrada zavisi od StatusReceipt i StatusIssue zapisa, kao i od toga da li se zapisi odnose na SalesLine, PurchLine ili nijedno. Već sada, gledate mnogo različitih kombinacija.
Recimo onda da znate da za sada trebate samo da se nosite sa pregršt kombinacija, ali takođe znate da će se od vas tražiti da budete u stanju da se nosite sa sve više i više kombinacija tokom vremena.
Hajde da bude relativno jednostavno i recimo da za sada treba samo da rukujete zapisima koji se odnose na SalesLine sa StatusIssue of ReservPhysical ili ReservOrdered, sve ostale kombinacije mogu biti ignorisane za sada, ali pošto znate da ćete morati da ih rešite kasnije, želećete da dizajnirate svoj kod na način koji ga čini lako proširivim.
Vaša hijerarhija za sada može izgledati ovako:
- Pretraga
- MyProcessor_Sales
- MyProcessor_Sales_ReservOrdered
- MyProcessor_Sales_ReservPhysical
- MyProcessor_Sales
Sada možete lako implementirati metod u super klasi koji instancira podklasu zasnovanu na ModuleInventPurchSales i StatusIssue enum. Ali tada ćete morati da modifikujete super klasu svaki put kada dodate podklasu, a to zapravo nije ideja nasleđivanja u objektno orijentisanom programiranju. Na kraju krajeva, ne morate da modifikujete RunBaseBatch ili SisOperationServiceBase svaki put kada dodate novi batch posao.
Umesto toga, možete koristiti SisEktension okvir. To će zahtevati da dodate još jednu klasu, koja treba da proširi SisAttribute. Ova klasa će se koristiti kao atribut sa kojim možete ukrasiti svoje časove obrade.
Ova klasa je veoma slična načinu na koji biste napravili klasu ugovora o podacima za implementaciju SisOperation-a, u tome što će imati neke članove podataka i parm metode za dobijanje i postavljanje tih vrednosti.
U našem slučaju, ClassDeclaration može izgledati ovako:
{
ModuleInventPurchSales module;
StatusIssue statusIssue;
StatusReceipt statusReceipt
}
Potrebno je da napravite novi () metod za instanciranje svih članova podataka. Ako želite možete dati neke ili sve od njih podrazumevane vrednosti, ali ja to nisam uradio.
StatusIssue _statusIssue,
StatusReceipt _statusReceipt)
{
;
super();
module = _module;
statusIssue = _statusIssue;
statusReceipt = _statusReceipt;
}
I takođe bi trebalo da implementirate parm metod za svakog člana podataka, ali ja sam ih ovde izostavio jer sam siguran da znate kako se to radi - u suprotnom, hajde da to smatramo vežbom ;-)
Sada možete da koristite svoju klasu atributa da ukrasite svaku od vaših klasa obrade. Na primer, deklaracije klase mogu 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, možete imenovati svoje klase kako god želite, važan deo ovde je da ukrasite svoje klase atributima koji odgovaraju vrsti obrade koju rade. (Ali imajte na umu da postoje konvencije imenovanja za hijerarhije klasa u Dinamics AKS-u i uvek je dobra ideja da ih pratite, ako je moguće).
Sada kada ste ukrasili svoje klase da biste identifikovali kakvu obradu svaki od njih radi, možete iskoristiti SisEktension okvir za instanciranje objekata podklasa po potrebi.
U svojoj super klasi (MiProcessor), možete dodati metodu konstrukcije ovako:
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 interesantan deo - i zaista objekat (oprostite na igri reči) celog ovog posta - je metoda getClassFromSysAttribute() u klasi SysExtensionAppClassFactori. Ono što ovaj metod radi jeste da prihvata ime super klase hijerarhije (a ova super klasa ne mora da bude na vrhu hijerarhije; to jednostavno znači da će samo klase koje proširuju ovu klasu biti podobne) i atributni objekat.
Zatim vraća objekat klase koji proširuje navedenu super klasu i ukrašen je odgovarajućim atributom.
Očigledno možete dodati onoliko daljnje validacije ili logike metodi konstrukcije koliko želite, ali važno je da jednom implementirate, nikada više ne biste trebali da modifikujete ovaj metod. Možete dodati podklase u hijerarhiju i sve dok se pobrinete da ih ukrasite na odgovarajući način, metoda konstrukcije će ih pronaći iako nisu postojale kada su napisane.
Šta je sa performansama? Iskreno nisam pokušao da ga uporedim, ali moj osećaj je da je ovo verovatno lošije od klasičnog dizajna prekidača. Međutim, s obzirom na to da je daleko većina problema sa performansama u Dinamics AKS-u uzrokovana pristupom bazi podataka, ne bih se previše brinuo o tome.
Naravno, ako implementirate nešto što će zahtevati hiljade objekata da se brzo kreiraju, možda ćete želeti da istražite dalje, ali u klasičnim slučajevima kada samo instancirate jedan objekat da biste uradili neku dugotrajnu obradu, sumnjam da će to biti važno. Takođe, s obzirom na moj savet za rešavanje problema (sledeći paragraf), čini se da se SisEktension okvir oslanja na keširanje, tako da u pokrenutom sistemu sumnjam da ima značajan pogodak performansi.
Rešavanje problema: Ako metoda konstrukcije ne pronađe vaše podklase iako ste sigurni da su pravilno uređene, to može biti problem keširanja. Pokušajte da obrišete keš memoriju i na klijentu i na serveru. Ne bi trebalo da bude neophodno da se zapravo ponovo pokrene AOS, ali to može biti poslednje sredstvo.