SysExtension Frameworki kasutamine Dynamics AX-i 2012 alamklassi leidmiseks
Avaldatud: 16. veebruar 2025, kell 00:25:39 UTC
Viimati uuendatud: 12. jaanuar 2026, kell 08:42:57 UTC
See artikkel kirjeldab, kuidas kasutada vähetuntud SysExtensioni raamistikku Dynamics AX 2012-s ja Dynamics 365 for Operationsis atribuutide kaunistuste põhjal alamklasside loomiseks, mis võimaldab töötlemisklasside hierarhia hõlpsasti laiendatavat kujundust.
Using the SysExtension Framework to Find Out Which Subclass to Instantiate in Dynamics AX 2012
Selle postituse teave põhineb Dynamics AX 2012 R3-l. See ei pruugi kehtida teiste versioonide puhul. (Värskendus: võin kinnitada, et selle artikli teave kehtib ka Dynamics 365 for Operationsi kohta)
Dynamics AX-is töötlemisklasside rakendamisel tuleb sageli luua klassihierarhia, kus iga alamklass vastab loendi väärtusele või on seotud mõne muu andmesidestusega. Klassikaline disain on selline, et ülemklassis on konstrukti meetod, millel on lüliti, mis määrab sisendi põhjal, millist klassi luua.
Põhimõtteliselt toimib see hästi, aga kui sul on palju erinevaid võimalikke sisendeid (loendis on palju elemente või sisend on mitme erineva väärtuse kombinatsioon), võib selle haldamine muutuda tüütuks ja veaohtlikuks ning disainil on alati puuduseks see, et pead nimetatud konstruktsioonimeetodit muutma, kui kunagi lisad uue alamklassi või teed muudatusi selles, millist alamklassi peaks millise sisendi põhjal kasutama.
Õnneks on olemas palju elegantsem, kuid kahjuks ka palju vähemtuntud viis selleks, nimelt SysExtensioni raamistiku kasutamine.
See raamistik kasutab ära atribuute, mida saate kasutada oma alamklasside kaunistamiseks, et süsteem suudaks välja selgitada, millist alamklassi mille käsitlemiseks kasutada. Teil on endiselt vaja konstrukti meetodit, kuid kui see on õigesti tehtud, ei pea te seda uute alamklasside lisamisel kunagi muutma.
Vaatame kujuteldavat näidet ja oletame, et kavatsete rakendada hierarhiat, mis teeb mingit tüüpi töötlust InventTrans tabeli põhjal. See, millist töötlust teha, sõltub kirjete StatusReceipt ja StatusIssue väärtustest, samuti sellest, kas kirjed on seotud SalesLine'iga, PurchLine'iga või mitte kummagagi. Juba praegu on teil palju erinevaid kombinatsioone.
Oletame siis, et sa tead, et praegu pead sa hakkama saama vaid käputäie kombinatsioonidega, aga sa tead ka, et aja jooksul palutakse sul olla võimeline hakkama saama üha rohkemate kombinatsioonidega.
Hoiame asja suhteliselt lihtsana ja ütleme, et praegu peate käsitlema ainult SalesLine'iga seotud kirjeid, mille StatusIssue on ReservPhysical või ReservOrdered. Kõiki teisi kombinatsioone võib praegu ignoreerida, kuid kuna teate, et peate neid hiljem käsitlema, peaksite oma koodi kujundama nii, et seda oleks lihtne laiendada.
Teie hierarhia võib praegu välja näha umbes selline:
- MinuProtsessorMinuProtsessor_MüükMinuProtsessor_Müügi_ReservTellitudMinuProtsessor_Müügi_ReservFüüsiline
Nüüd saaksite superklassis hõlpsalt rakendada meetodit, mis loob alamklassi eksemplari ModuleInventPurchSales ja StatusIssue enumi põhjal. Kuid siis peate iga kord, kui lisate alamklassi, superklassi muutma ja see pole tegelikult objektorienteeritud programmeerimise pärimise idee. Lõppude lõpuks ei pea te RunBaseBatchi ega SysOperationServiceBase'i muutma iga kord, kui lisate uue paketitöö.
Selle asemel võite kasutada SysExtensioni raamistikku. See nõuab teilt teise klassi lisamist, mis peab laiendama SysAttribute'i. Seda klassi kasutatakse atribuudina, millega saate oma töötlusklasse kaunistada.
See klass on väga sarnane SysOperationi implementatsiooni jaoks andmelepingu klassi loomisele, kuna sellel on mõned andmeliikmed ja parm-meetodid nende väärtuste hankimiseks ja määramiseks.
Meie puhul võib klassideklaratsioon välja näha umbes selline:
{
ModuleInventPurchSales module;
StatusIssue statusIssue;
StatusReceipt statusReceipt
}
Kõigi andmeliikmete eksemplaride loomiseks on vaja luua meetod new(). Soovi korral saab mõnele või kõigile anda vaikeväärtused, aga mina pole seda teinud.
StatusIssue _statusIssue,
StatusReceipt _statusReceipt)
{
;
super();
module = _module;
statusIssue = _statusIssue;
statusReceipt = _statusReceipt;
}
Ja sa peaksid iga andmeliikme jaoks ka parm-meetodi rakendama, aga ma olen need siin välja jätnud, kuna ma olen kindel, et sa tead, kuidas seda teha - vastasel juhul vaatame seda harjutusena ;-)
Nüüd saate oma atribuudiklassi kasutada iga töötlusklassi kaunistamiseks. Näiteks võiksid klassideklaratsioonid välja näha sellised:
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
{
}
Muidugi võite oma klasse nimetada kuidas iganes soovite, oluline on siin see, et lisaksite oma klassidele atribuudid, mis vastavad nende teostatavale töötlusviisile. (Kuid pidage meeles, et Dynamics AX-is on klasside hierarhiatel nimetamiskonventsioonid ja võimaluse korral on alati hea mõte neid järgida).
Nüüd, kui olete oma klassid vastavalt vajadusele töötlemistoimingute tüübile määranud, saate SysExtensioni raamistikku ära kasutada alamklasside objektide eksemplaride loomiseks.
Oma superklassis (MyProcessor) võiksid lisada sellise konstruktsioonimeetodi:
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;
}
Tõeliselt huvitav osa – ja tegelikult kogu selle postituse objekt (vabandust sõnamängu pärast) – on SysExtensionAppClassFactory klassi meetod getClassFromSysAttribute(). See meetod aktsepteerib hierarhia ülemklassi nime (ja see ülemklass ei pea olema hierarhia tipus; see tähendab lihtsalt, et ainult seda klassi laiendavad klassid on abikõlblikud) ja atribuudiobjekti.
Seejärel tagastab see klassi objekti, mis laiendab määratud ülemklassi ja on kaunistatud vastava atribuudiga.
Loomulikult saab meetodile „construct“ lisada nii palju valideerimist või loogikat, kui soovitakse, aga oluline on see, et kui see meetod on juba rakendatud, ei pea seda enam kunagi muutma. Hierarhiasse saab lisada alamklasse ja kui need on sobivalt kaunistatud, leiab meetod „construct“ need üles isegi siis, kui neid meetodi kirjutamise ajal polnud olemas.
Aga jõudlus? Ausalt öeldes pole ma proovinud seda võrdlusanalüüsida, aga minu sisetunne ütleb, et see toimib ilmselt halvemini kui klassikaline switch-lause. Arvestades aga, et Dynamics AX-i jõudlusprobleemid on vaieldamatult põhjustatud andmebaasile juurdepääsust, ei muretseks ma selle pärast liiga palju.
Muidugi, kui rakendate midagi, mis nõuab tuhandete objektide kiiret loomist, võiksite seda lähemalt uurida, kuid klassikalistel juhtudel, kus lihtsalt loote ühe objekti pika töötlemise jaoks, kahtlen, kas see oluline on. Samuti, arvestades minu tõrkeotsingu näpunäidet (järgmine lõik), tundub, et SysExtensioni raamistik tugineb vahemällu salvestamisele, seega kahtlen, kas töötavas süsteemis on sellel märkimisväärne jõudluslangus.
Veaotsing: Kui konstrukti meetod ei leia teie alamklasse, kuigi olete kindel, et need on õigesti sisustatud, võib tegemist olla vahemäluprobleemiga. Proovige tühjendada vahemälud nii kliendis kui ka serveris. AOS-i taaskäivitamine ei tohiks olla vajalik, kuid see võib olla viimane abinõu.
Lisalugemist
Kui see postitus teile meeldis, võivad teile meeldida ka need soovitused:
- Teisendage reaal kõigi kümnendkohtadega stringiks rakenduses Dynamics AX 2012
- Päringu kasutamine SysOperationi andmelepinguklassis Dynamics AX-i 2012-s
- Viga "Andmelepingu objekti jaoks pole metaandmete klass määratletud" rakenduses Dynamics AX 2012
