Uporaba ogrodja SysExtension Framework, da ugotovite, kateri podrazred ustvariti v Dynamics AX 2012
Objavljeno: 16. februar 2025 ob 12:25:59 dop. UTC
Nazadnje posodobljeno: 12. januar 2026 ob 8:43:17 dop. UTC
Ta članek opisuje, kako uporabiti manj znano ogrodje SysExtension v programih Dynamics AX 2012 in Dynamics 365 for Operations za ustvarjanje podrazredov na podlagi okraskov atributov, kar omogoča enostavno razširljivo zasnovo hierarhije razredov obdelave.
Using the SysExtension Framework to Find Out Which Subclass to Instantiate in Dynamics AX 2012
Informacije v tej objavi temeljijo na programu Dynamics AX 2012 R3. Morda veljajo za druge različice, morda pa tudi ne. (Posodobitev: Lahko potrdim, da so informacije v tem članku veljavne tudi za Dynamics 365 for Operations.)
Pri implementaciji razredov za obdelavo v Dynamics AX se pogosto soočate z ustvarjanjem hierarhije razredov, v kateri vsak podrazred ustreza vrednosti naštevanja ali ima neko drugo podatkovno povezavo. Klasična zasnova je, da se v nadrazredu nato doda metoda konstrukta, ki ima stikalo, ki na podlagi vhodnih podatkov določi, kateri razred naj se ustvari.
Načeloma to deluje dobro, če pa imate veliko različnih možnih vhodnih podatkov (veliko elementov v naštevanju ali pa je vhod morda kombinacija več različnih vrednosti), lahko vzdrževanje postane dolgočasno in nagnjeno k napakam, zasnova pa ima vedno slabost, da boste morali spremeniti omenjeno metodo konstruiranja, če kdaj dodate nov podrazred ali spremenite, kateri podrazred naj se uporabi glede na kateri vhod.
Na srečo obstaja veliko bolj eleganten, a žal tudi veliko manj znan način za to, in sicer z uporabo ogrodja SysExtension.
Ta ogrodje izkorišča atribute, ki jih lahko uporabite za okrasitev podrazredov, da sistem lahko ugotovi, kateri podrazred naj se uporabi za obravnavo česa. Še vedno boste potrebovali metodo konstruiranja, če pa je pravilno narejena, je ne bo treba nikoli spreminjati pri dodajanju novih podrazredov.
Poglejmo si namišljen primer in recimo, da boste implementirali hierarhijo, ki izvaja nekakšno obdelavo na podlagi tabele InventTrans. Katera obdelava bo izvedena, je odvisno od StatusReceipt in StatusIssue zapisov, pa tudi od tega, ali so zapisi povezani s SalesLine, PurchLine ali ničim. Že zdaj imate na voljo veliko različnih kombinacij.
Recimo, da veste, da morate zaenkrat obravnavati le peščico kombinacij, vendar veste tudi, da boste sčasoma morali obvladati vedno več kombinacij.
Naj bo relativno preprosto in recimo, da morate zaenkrat obravnavati le zapise, povezane s SalesLine, s statusom ReservPhysical ali ReservOrdered, vse druge kombinacije pa lahko zaenkrat prezrete, ker pa veste, da jih boste morali obravnavati pozneje, boste želeli svojo kodo oblikovati tako, da jo bo mogoče enostavno razširiti.
Vaša hierarhija bi lahko zaenkrat izgledala nekako takole:
- MojProcesorMojProcesorProdajaMojaProcesorProdajna_RezervaNaročenoMojaProcesorProdajna_RezervaFizično
Zdaj bi lahko v nadrazredu preprosto implementirali metodo, ki ustvari podrazred na podlagi ModuleInventPurchSales in naštevanja StatusIssue. Vendar boste nato morali nadrazred spreminjati vsakič, ko dodate podrazred, in to ni prava ideja dedovanja v objektno usmerjenem programiranju. Navsezadnje vam ni treba spreminjati RunBaseBatch ali SysOperationServiceBase vsakič, ko dodate novo paketno opravilo.
Namesto tega lahko uporabite ogrodje SysExtension. To bo zahtevalo dodajanje še enega razreda, ki mora razširiti SysAttribute. Ta razred bo uporabljen kot atribut, s katerim lahko okrasite svoje razrede za obdelavo.
Ta razred je zelo podoben načinu, kako bi ustvarili razred podatkovnih pogodb za implementacijo SysOperation, saj bo imel nekaj podatkovnih članov in parm metode za pridobivanje in nastavitev teh vrednosti.
V našem primeru bi lahko deklaracija razreda izgledala nekako takole:
{
ModuleInventPurchSales module;
StatusIssue statusIssue;
StatusReceipt statusReceipt
}
Za ustvarjanje primerkov vseh podatkovnih članov morate ustvariti metodo new(). Če želite, lahko nekaterim ali vsem dodelite privzete vrednosti, vendar tega še nisem storil.
StatusIssue _statusIssue,
StatusReceipt _statusReceipt)
{
;
super();
module = _module;
statusIssue = _statusIssue;
statusReceipt = _statusReceipt;
}
Prav tako bi morali za vsak podatkovni član implementirati metodo parm, vendar sem jih tukaj izpustil, ker sem prepričan, da veste, kako to storiti - sicer pa si to predstavljajmo kot vajo ;-)
Zdaj lahko s svojim razredom atributov okrasite vsak od svojih razredov obdelave. Deklaracije razredov bi lahko na primer izgledale takole:
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
{
}
Seveda lahko svoje razrede poimenujete kakor koli želite, pomembno pa je, da jih okrasite z atributi, ki ustrezajo vrsti obdelave, ki jo izvajajo. (Vendar ne pozabite, da v Dynamics AX obstajajo konvencije poimenovanja za hierarhije razredov in vedno je dobro, da jih upoštevate, če je le mogoče).
Zdaj, ko ste svoje razrede okrasili tako, da določite, kakšno obdelavo izvaja vsak od njih, lahko po potrebi izkoristite ogrodje SysExtension za ustvarjanje instanc objektov podrazredov.
V vašem nadrazredu (MyProcessor) lahko dodate metodo konstruiranja, kot je ta:
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;
}
Resnično zanimiv del – in pravzaprav predmet (oprostite za besedno igro) celotne objave – je metoda getClassFromSysAttribute() v razredu SysExtensionAppClassFactory. Ta metoda sprejme ime nadrazreda hierarhije (in ta nadrazred ni nujno na vrhu hierarhije; to preprosto pomeni, da bodo primerni le razredi, ki razširjajo ta razred) in objekt atributa.
Nato vrne objekt razreda, ki razširja določeni nadrazred in je okrašen z ustreznim atributom.
Metodi konstrukt lahko seveda dodate toliko dodatne validacije ali logike, kot želite, vendar je pomembno, da te metode, ko jo enkrat implementirate, ne bi smeli nikoli več spreminjati. Hierarhiji lahko dodate podrazrede in če jih ustrezno okrasite, jih bo metoda konstrukt našla, tudi če v času pisanja niso obstajali.
Kaj pa zmogljivost? Iskreno povedano, nisem poskušal primerjati zmogljivosti, vendar imam občutek, da se ta verjetno obnese slabše kot klasična zasnova stavka switch. Glede na to, da daleč največ težav z zmogljivostjo v Dynamics AX povzroča dostop do baze podatkov, se zaradi tega ne bi preveč obremenjeval.
Seveda, če implementirate nekaj, kar bo zahtevalo hitro ustvarjanje tisočev objektov, boste morda želeli podrobneje raziskati, vendar v klasičnih primerih, ko ustvarite samo en objekt za dolgotrajno obdelavo, dvomim, da bo to pomembno. Glede na moj nasvet za odpravljanje težav (naslednji odstavek) se zdi, da se ogrodje SysExtension zanaša na predpomnjenje, zato dvomim, da ima v delujočem sistemu znaten vpliv na zmogljivost.
Odpravljanje težav: Če metoda konstrukta ne najde vaših podrazredov, čeprav ste prepričani, da so pravilno urejeni, je lahko težava v predpomnjenju. Poskusite počistiti predpomnilnike na odjemalcu in strežniku. Ni bi smelo biti treba dejansko znova zagnati AOS, vendar je to morda zadnja možnost.
Nadaljnje branje
Če vam je bila ta objava všeč, vam bodo morda všeč tudi ti predlogi:
- Pretvorite realno v niz z vsemi decimalkami v Dynamics AX 2012
- Uporaba poizvedbe v podatkovnem pogodbenem razredu SysOperation v Dynamics AX 2012
- Kako ponoviti elemente enuma iz kode X++ v Dynamics AX 2012
