A SysExtension Framework segítségével megtudhatja, melyik alosztályt kell példányosítani a Dynamics AX 2012-ben
Megjelent: 2025. február 16. 0:25:42 UTC
Ez a cikk leírja, hogyan használhatja a kevéssé ismert SysExtension keretrendszert a Dynamics AX 2012 és Dynamics 365 for Operations rendszerben az attribútumdíszítéseken alapuló alosztályok példányosítására, lehetővé téve a feldolgozási osztályhierarchia könnyen bővíthető kialakítását.
Using the SysExtension Framework to Find Out Which Subclass to Instantiate in Dynamics AX 2012
A bejegyzésben található információk a Dynamics AX 2012 R3-on alapulnak. Lehet, hogy más verziókra érvényes, de lehet, hogy nem. (Frissítés: Megerősíthetem, hogy a cikkben szereplő információk a Dynamics 365 for Operations esetében is érvényesek)
Amikor feldolgozási osztályokat implementál a Dynamics AX-ben, gyakran szembe kell néznie egy olyan osztályhierarchia létrehozásával, amelyben minden egyes alosztály egy enum értéknek felel meg, vagy más adatcsatolást tartalmaz. A klasszikus kialakítás az, hogy a szuperosztályban van egy konstrukciós metódus, amely egy kapcsolóval rendelkezik, amely meghatározza, hogy melyik osztályt kell példányosítani a bemenet alapján.
Ez elvileg jól működik, de ha sok különböző lehetséges bemenet van (sok elem egy enumban, vagy esetleg a bemenet több különböző érték kombinációja), akkor fárasztó és hibalehetővé válhat a karbantartása, és a tervezésnek mindig megvan az a hátránya, hogy módosítania kell az említett konstrukciós metódust, ha új alosztályt ad hozzá, vagy módosítja, hogy melyik alosztályt melyik bemenet alapján kell használni.
Szerencsére van ennek egy sokkal elegánsabb, de sajnos sokkal kevésbé ismert módja is, mégpedig a SysExtension keretrendszer használatával.
Ez a keretrendszer kihasználja azokat az attribútumokat, amelyekkel díszítheti az alosztályait, hogy a rendszer képes legyen kitalálni, hogy melyik alosztályt kell használni a kezeléséhez. Továbbra is szüksége lesz egy konstrukciós metódusra, de ha jól csinálja, soha nem kell módosítania új alosztályok hozzáadásakor.
Nézzünk egy képzeletbeli példát, és mondjuk, hogy olyan hierarchiát fogunk megvalósítani, amely valamilyen feldolgozást végez az InventTrans tábla alapján. A végrehajtandó feldolgozás a rekordok StatusReceipt és StatusIssue értékétől, valamint attól függ, hogy a rekordok kapcsolódnak-e a SalesLine-hoz, a PurchLine-hoz vagy egyikhez sem. Már most is sok különböző kombinációt nézeget.
Tegyük fel, hogy tudja, hogy egyelőre csak néhány kombinációt kell kezelnie, de azt is tudja, hogy idővel egyre több kombinációt kell kezelnie.
Maradjunk viszonylag egyszerűek és mondjuk, hogy egyelőre csak a ReservPhysical vagy ReservOrdered StatusIssue állapotú SalesLine-hoz kapcsolódó rekordokat kell kezelni, az összes többi kombinációt egyelőre figyelmen kívül hagyhatjuk, de mivel tudjuk, hogy később kezelni kell őket, érdemes úgy megtervezni a kódot, hogy könnyen bővíthető legyen.
A hierarchiája jelenleg valahogy így nézhet ki:
- MyProcessor
- MyProcessor_Sales
- MyProcessor_Sales_ReservOrdered
- MyProcessor_Sales_ReservPhysical
- MyProcessor_Sales
Most könnyen megvalósíthat egy metódust a szuperosztályban, amely egy ModuleInventPurchSales és egy StatusIssue enum alapján példányosít egy alosztályt. De ezután minden alkalommal módosítania kell a szuperosztályt, amikor egy alosztályt ad hozzá, és ez valójában nem az öröklődés gondolata az objektum-orientált programozásban. Végül is nem kell minden alkalommal módosítania a RunBaseBatch vagy a SysOperationServiceBase szolgáltatást, amikor új kötegelt feladatot ad hozzá.
Ehelyett használhatja a SysExtension keretrendszert. Ehhez egy másik osztályt kell hozzáadnia, amelyhez ki kell bővítenie a SysAttribute-t. Ez az osztály lesz az attribútum, amellyel díszítheti a feldolgozási osztályokat.
Ez az osztály nagyon hasonlít ahhoz, ahogyan egy SysOperation implementációhoz adatszerződés-osztályt készítene, mivel tartalmaz néhány adattagot és parm metódusokat az értékek lekéréséhez és beállításához.
Esetünkben a ClassDeclaration valahogy így nézhet ki:
{
ModuleInventPurchSales module;
StatusIssue statusIssue;
StatusReceipt statusReceipt
}
Az összes adattag példányosításához új() metódust kell készítenie. Ha szeretné, megadhat néhány vagy mindegyik alapértelmezett értéket, de én ezt nem tettem meg.
StatusIssue _statusIssue,
StatusReceipt _statusReceipt)
{
;
super();
module = _module;
statusIssue = _statusIssue;
statusReceipt = _statusReceipt;
}
Illetve minden adattaghoz be kell építeni egy parm metódust is, de ezeket itt kihagytam, mert biztos vagyok benne, hogy tudja, hogyan kell ezt csinálni – különben tekintsük gyakorlatnak ;-)
Most már használhatja az attribútumosztályt az egyes feldolgozási osztályok díszítésére. Például az osztálydeklarációk így nézhetnek ki:
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
{
}
Az osztályokat természetesen tetszés szerint nevezheti el, itt az a fontos, hogy az osztályokat olyan attribútumokkal díszítse, amelyek megfelelnek annak, hogy milyen feldolgozást végeznek. (De ne feledje, hogy a Dynamics AX-ben léteznek elnevezési konvenciók az osztályhierarchiákhoz, és mindig jó ötlet ezeket követni, ha lehetséges).
Most, hogy feldíszítette osztályait, hogy azonosítsa, milyen feldolgozást végeznek mindegyikük, kihasználhatja a SysExtension keretrendszert az alosztályok objektumainak szükség szerinti példányosítására.
A szuper osztályban (MyProcessor) hozzáadhat egy ilyen konstrukciós metódust:
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;
}
Az igazán érdekes része – és valójában az egész bejegyzés tárgya (bocsánat a szójátékért) – a getClassFromSysAttribute() metódus a SysExtensionAppClassFactory osztályban. Ez a metódus az, hogy elfogadja egy hierarchia szuperosztályának nevét (és ennek a szuperosztálynak nem kell a hierarchia tetején lennie; ez egyszerűen azt jelenti, hogy csak az ezt az osztályt kiterjesztő osztályok lesznek jogosultak) és egy attribútum objektumot.
Ezután egy olyan osztály objektumát ad vissza, amely kiterjeszti a megadott szuperosztályt , és egy megfelelő attribútummal van díszítve.
Nyilvánvalóan annyi további érvényesítést vagy logikát adhat hozzá a konstrukciós metódushoz, amennyit csak akar, de itt az a fontos kivonat, hogy a megvalósítás után soha többé nem kell módosítania ezt a metódust. Hozzáadhat alosztályokat a hierarchiához, és mindaddig, amíg gondoskodik a megfelelő díszítésről, a construct metódus meg fogja találni őket, még akkor is, ha írásakor még nem léteztek.
Mi a helyzet a teljesítménnyel? Őszintén szólva, nem próbáltam összehasonlítani, de az a belső érzésem, hogy ez valószínűleg rosszabbul teljesít, mint a klasszikus switch-utasítás. Figyelembe véve azonban, hogy a Dynamics AX teljesítményével kapcsolatos problémákat messze az adatbázis-hozzáférés okozza, nem aggódnék emiatt.
Természetesen, ha olyasvalamit valósít meg, amelyhez több ezer objektum gyors létrehozása szükséges, érdemes tovább vizsgálnia, de a klasszikus esetekben, amikor csak egyetlen objektumot példányosítunk hosszas feldolgozáshoz, kétlem, hogy számítana. Figyelembe véve a hibaelhárítási tippemet (következő bekezdés), úgy tűnik, hogy a SysExtension keretrendszer a gyorsítótárazásra támaszkodik, ezért egy futó rendszerben kétlem, hogy jelentős teljesítményt rontott volna. Hibaelhárítás: Ha a konstrukciós metódus nem találja meg az alosztályait, annak ellenére, hogy biztos benne, hogy helyesen vannak díszítve, akkor ez gyorsítótárazási probléma lehet. Próbálja meg törölni a gyorsítótárakat mind a kliensen, mind a szerveren. Nem kell ténylegesen újraindítani az AOS-t, de lehet, hogy az utolsó lehetőség.