SysExtension Framework izmantošana, lai uzzinātu, kuru apakšklasi iemiesot programmā Dynamics AX 2012
Publicēts: 2025. gada 16. februāris 00:25:51 UTC
Šajā rakstā ir aprakstīts, kā lietot mazpazīstamo SysExtension ietvaru programmās Dynamics AX 2012 un Dynamics 365 for Operations, lai izveidotu apakšklases, kuru pamatā ir atribūtu dekorācijas, ļaujot viegli paplašināmu apstrādes klašu hierarhijas dizainu.
Using the SysExtension Framework to Find Out Which Subclass to Instantiate in Dynamics AX 2012
Šajā ziņā sniegtā informācija ir balstīta uz Dynamics AX 2012 R3. Tas var būt un var nebūt derīgs citām versijām. (Atjauninājums: varu apstiprināt, ka šajā rakstā sniegtā informācija ir derīga arī Dynamics 365 for Operations)
Ieviešot apstrādes klases programmā Dynamics AX, jūs bieži saskaraties ar klases hierarhijas izveidi, kurā katra apakšklase atbilst enum vērtībai vai tai ir kāda cita datu saite. Klasisks dizains paredz, ka superklasē ir konstruēšanas metode, kurai ir slēdzis, kas nosaka, kuru klasi izveidot, pamatojoties uz ievadi.
Tas principā darbojas labi, bet, ja jums ir daudz dažādu iespējamo ievades veidu (daudz elementu sarakstā vai, iespējams, ievade ir vairāku dažādu vērtību kombinācija), to uzturēšana var kļūt apnicīga un ar kļūdām, un dizainam vienmēr ir tāds trūkums, ka jums būs jāmaina minētā konstruēšanas metode, ja kādreiz pievienosit jaunu apakšklasi vai veiksit izmaiņas, kura apakšklase jāizmanto, pamatojoties uz kuru ievadi.
Par laimi, ir daudz elegantāks, bet diemžēl arī mazāk zināms veids, kā to izdarīt, proti, izmantojot SysExtension ietvaru.
Šī sistēma izmanto atribūtus, kurus varat izmantot, lai dekorētu savas apakšklases, lai sistēma varētu izdomāt, kura apakšklase ir jāizmanto, lai apstrādātu to. Jums joprojām būs nepieciešama konstruēšanas metode, taču, ja tā tiek veikta pareizi, jums tā nekad nebūs jāmaina, pievienojot jaunas apakšklases.
Apskatīsim iedomātu piemēru un sakām, ka jūs gatavojaties ieviest hierarhiju, kas veic sava veida apstrādi, pamatojoties uz InventTrans tabulu. Apstrāde ir atkarīga no ierakstu StatusReceipt un StatusIssue, kā arī no tā, vai ieraksti ir saistīti ar SalesLine, PurchLine vai ne. Jau tagad jūs skatāties uz daudzām dažādām kombinācijām.
Pieņemsim, ka jūs zināt, ka pagaidām jums ir jāapstrādā tikai dažas kombinācijas, taču jūs arī zināt, ka laika gaitā jums tiks lūgts spēt apstrādāt arvien vairāk kombināciju.
Paturēsim to samērā vienkārši un teiksim, ka pagaidām jums ir jāapstrādā tikai ar SalesLine saistīti ieraksti, kuru statuss ir ReservPhysical vai ReservOrdered. Visas pārējās kombinācijas pagaidām var ignorēt, taču, tā kā zināt, ka tās būs jāapstrādā vēlāk, vēlēsities izveidot kodu tā, lai tas būtu viegli paplašināms.
Jūsu hierarhija pašlaik var izskatīties šādi:
- MyProcessor
- MyProcessor_Sales
- MyProcessor_Sales_ReservOrdered
- MyProcessor_Sales_ReservPhysical
- MyProcessor_Sales
Tagad superklasē varat viegli ieviest metodi, kas izveido apakšklasi, kuras pamatā ir ModuleInventPurchSales un StatusIssue enum. Bet pēc tam jums būs jāmaina superklase katru reizi, kad pievienojat apakšklasi, un tā patiesībā nav mantojuma ideja objektorientētā programmēšanā. Galu galā jums nav jāmaina RunBaseBatch vai SysOperationServiceBase katru reizi, kad pievienojat jaunu pakešdarbu.
Tā vietā varat izmantot SysExtension ietvaru. Tam būs jāpievieno cita klase, kurai jāpaplašina SysAttribute. Šī klase tiks izmantota kā atribūts, ar kuru varat izrotāt apstrādes nodarbības.
Šī klase ir ļoti līdzīga tam, kā izveidot datu līguma klasi SysOperation ieviešanai, jo tajā būs daži datu dalībnieki un parametru metodes šo vērtību iegūšanai un iestatīšanai.
Mūsu gadījumā klases deklarācija var izskatīties šādi:
{
ModuleInventPurchSales module;
StatusIssue statusIssue;
StatusReceipt statusReceipt
}
Jums ir jāizveido jauna() metode visu datu dalībnieku iemūžināšanai. Ja vēlaties, varat norādīt dažas vai visas no tām noklusējuma vērtības, bet es to neesmu izdarījis.
StatusIssue _statusIssue,
StatusReceipt _statusReceipt)
{
;
super();
module = _module;
statusIssue = _statusIssue;
statusReceipt = _statusReceipt;
}
Un jums vajadzētu arī ieviest parm metodi katram datu dalībniekam, taču es tās esmu izlaidis, jo esmu pārliecināts, ka jūs zināt, kā to izdarīt — pretējā gadījumā uzskatīsim to par uzdevumu ;-)
Tagad varat izmantot savu atribūtu klasi, lai dekorētu katru apstrādes klasi. Piemēram, klases deklarācijas varētu izskatīties šādi:
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
{
}
Protams, jūs varat nosaukt savas nodarbības, kā vēlaties, šeit ir svarīgi, lai jūs izrotātu savas nodarbības ar atribūtiem, kas atbilst to apstrādes veidam. (Taču ņemiet vērā, ka Dynamics AX klašu hierarhijām pastāv nosaukumu piešķiršanas konvencijas, un vienmēr ir ieteicams tos ievērot, ja iespējams).
Tagad, kad esat izkārtojis savas klases, lai noteiktu, kāda veida apstrādi veic katra no tām, varat izmantot SysExtension ietvaru, lai pēc vajadzības iemiesotu apakšklases objektus.
Savā superklasē (MyProcessor) varat pievienot šādu konstruēšanas metodi:
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;
}
Patiešām interesantā daļa — un patiešām visa šī ziņojuma objekts (atvainojiet par vārdu spēli) ir metode getClassFromSysAttribute() klasē SysExtensionAppClassFactory. Šī metode ir tāda, ka tā pieņem hierarhijas superklases nosaukumu (un šai superklasei nav jāatrodas hierarhijas augšgalā ; tas vienkārši nozīmē, ka būs piemērotas tikai klases, kas paplašina šo klasi) un atribūta objektu.
Pēc tam tas atgriež klases objektu, kas paplašina norādīto superklasi un ir dekorēts ar atbilstošu atribūtu.
Acīmredzot varat pievienot konstruēšanas metodei tik daudz papildu apstiprināšanas vai loģikas, cik vēlaties, taču šeit ir svarīgi, ka pēc ieviešanas šī metode vairs nav jāmaina. Jūs varat pievienot apakšklases hierarhijai, un, ja vien pārliecināsieties, ka tās ir atbilstoši dekorētas, konstruēšanas metode tās atradīs, pat ja tās nepastāvēja, kad tā tika rakstīta.
Kā ar sniegumu? Godīgi sakot, es neesmu mēģinājis to salīdzināt, bet mana iekšējā sajūta ir tāda, ka tas , iespējams, darbojas sliktāk nekā klasiskais slēdža paziņojuma dizains. Tomēr, ņemot vērā, ka lielākā daļa Dynamics AX veiktspējas problēmu rada piekļuve datubāzei, es par to pārāk neuztraucos.
Protams, ja ieviešat kaut ko tādu, kam būs nepieciešams ātri izveidot tūkstošiem objektu, iespējams, vēlēsities izmeklēt sīkāk, taču klasiskajos gadījumos, kad vienkārši izveidojat vienu objektu, lai veiktu ilgstošu apstrādi, šaubos, vai tam būs nozīme. Turklāt, ņemot vērā manu problēmu novēršanas padomu (nākamā rindkopa), šķiet, ka SysExtension ietvars balstās uz kešatmiņu, tāpēc es šaubos, ka darbojošā sistēmā tai ir ievērojams veiktspējas trieciens. Problēmu novēršana: ja konstruēšanas metode neatrod jūsu apakšklases, lai gan esat pārliecināts, ka tās ir pareizi noformētas, tā var būt kešatmiņas problēma. Mēģiniet notīrīt kešatmiņu gan klientā, gan serverī. Nav nepieciešams faktiski restartēt AOS, taču tas var būt pēdējais līdzeklis.