SysExtension Frameworkin käyttäminen Dynamics AX 2012:ssa luotavan alaluokan selvittämiseen
Julkaistu: 16. helmikuuta 2025 klo 0.25.40 UTC
Tässä artikkelissa kuvataan, kuinka vähän tunnettua SysExtension-kehystä käytetään Dynamics AX 2012:ssa ja Dynamics 365 for Operationsissa alaluokkien luomiseen attribuuttien koristelujen perusteella, mikä mahdollistaa käsittelyluokkahierarkian helposti laajennettavan suunnittelun.
Using the SysExtension Framework to Find Out Which Subclass to Instantiate in Dynamics AX 2012
Tämän viestin tiedot perustuvat Dynamics AX 2012 R3:een. Se voi olla tai ei ole voimassa muille versioille. (Päivitys: Voin vahvistaa, että tämän artikkelin tiedot koskevat myös Dynamics 365 for Operationsia)
Kun toteutat käsittelyluokkia Dynamics AX:ssä, joudut usein luomaan luokkahierarkian, jossa jokainen alaluokka vastaa enum-arvoa tai jolla on jokin muu datakytkentä. Klassisen mallin mukaan superluokassa on sitten konstruktiomenetelmä, jossa on kytkin, joka määrittää, mikä luokka instantioidaan syötteen perusteella.
Tämä toimii periaatteessa hyvin, mutta jos sinulla on monia erilaisia mahdollisia syötteitä (monia elementtejä enumissa tai syöte on ehkä useiden eri arvojen yhdistelmä), sen ylläpito voi olla tylsää ja virhealtista, ja suunnittelussa on aina se haittapuoli, että joudut muokkaamaan mainittua rakennusmenetelmää, jos lisäät uuden alaluokan tai teet muutoksia mihin alaluokkaan tulee käyttää minkä syötteen perusteella.
Onneksi on olemassa paljon tyylikkäämpi, mutta valitettavasti myös vähemmän tunnettu tapa tehdä tämä, nimittäin SysExtension-kehystä.
Tämä kehys hyödyntää attribuutteja, joita voit käyttää alaluokkien koristeluun, jotta järjestelmä pystyy selvittämään, mitä alaluokkaa tulisi käyttää käsittelemään mitä. Tarvitset silti konstruktiomenetelmän, mutta jos se tehdään oikein, sinun ei koskaan tarvitse muokata sitä, kun lisäät uusia alaluokkia.
Katsotaanpa kuvitteellista esimerkkiä ja sanotaan, että aiot ottaa käyttöön hierarkian, joka suorittaa jonkinlaisen käsittelyn InventTrans-taulukon perusteella. Tehtävä käsittely riippuu tietueiden StatusReceipt- ja StatusIssue-arvoista sekä siitä, liittyvätkö tietueet SalesLine-, PurchLine- tai ei kumpaankaan. Katselet jo nyt monia erilaisia yhdistelmiä.
Oletetaan sitten, että tiedät, että toistaiseksi sinun tarvitsee käsitellä vain kourallinen yhdistelmiä, mutta tiedät myös, että sinua pyydetään pystymään käsittelemään yhä useampia yhdistelmiä ajan myötä.
Pidetään se suhteellisen yksinkertaisena ja sanotaan, että toistaiseksi sinun tarvitsee käsitellä vain SalesLinen tietueita, joiden StatusIssue on ReservPhysical tai ReservOrdered, kaikki muut yhdistelmät voidaan toistaiseksi jättää huomiotta, mutta koska tiedät, että sinun on käsiteltävä niitä myöhemmin, sinun kannattaa suunnitella koodisi siten, että se on helposti laajennettavissa.
Hierarkiasi voi näyttää tällä hetkellä tältä:
- MyProcessor
- MyProcessor_Sales
- MyProcessor_Sales_ReservOrdered
- MyProcessor_Sales_ReservPhysical
- MyProcessor_Sales
Nyt voit helposti toteuttaa superluokassa menetelmän, joka luo aliluokan ModuleInventPurchSales- ja StatusIssue-enumiin perustuen. Mutta sinun on sitten muokattava superluokkaa joka kerta, kun lisäät aliluokan, eikä se oikeastaan ole periytymisen idea olio-ohjelmoinnissa. Loppujen lopuksi sinun ei tarvitse muokata RunBaseBatch- tai SysOperationServiceBasea joka kerta, kun lisäät uuden erätyön.
Sen sijaan voit käyttää SysExtension-kehystä. Tämä edellyttää, että lisäät toisen luokan, jonka on laajennettava SysAttributea. Tätä luokkaa käytetään attribuuttina, jolla voit koristella käsittelyluokkasi.
Tämä luokka on hyvin samanlainen kuin tekisit tietosopimusluokan SysOperation-toteutukselle, sillä siinä on joitain datajäseniä ja parm-menetelmiä näiden arvojen saamiseksi ja asettamiseen.
Meidän tapauksessamme ClassDeclaration voi näyttää tältä:
{
ModuleInventPurchSales module;
StatusIssue statusIssue;
StatusReceipt statusReceipt
}
Sinun on tehtävä uusi()-menetelmä kaikkien datajäsenten instantoimiseksi. Halutessasi voit antaa osan tai kaikki oletusarvot, mutta en ole tehnyt sitä.
StatusIssue _statusIssue,
StatusReceipt _statusReceipt)
{
;
super();
module = _module;
statusIssue = _statusIssue;
statusReceipt = _statusReceipt;
}
Ja sinun pitäisi myös ottaa käyttöön parm-menetelmä jokaiselle datajäsenelle, mutta jätin ne täältä pois, koska tiedät varmasti kuinka se tehdään - muuten katsotaanpa harjoitukseksi ;-)
Nyt voit käyttää attribuuttiluokkaasi jokaisen käsittelyluokkasi koristeluun. Luokkailmoitukset voisivat näyttää esimerkiksi tältä:
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
{
}
Voit tietysti nimetä luokkasi haluamallasi tavalla, tärkeintä tässä on, että koristat luokkasi attribuutteilla, jotka vastaavat niiden käsittelyä. (Mutta muista, että Dynamics AX:ssä on luokkahierarkioiden nimeämiskäytäntöjä, ja niitä on aina hyvä noudattaa, jos mahdollista).
Nyt kun olet koristellut luokkasi tunnistamaan, millaista käsittelyä kukin niistä tekee, voit hyödyntää SysExtension-kehystä aliluokkien objektien ilmentämiseen tarpeen mukaan.
Superluokkaasi (MyProcessor) voit lisätä seuraavanlaisen konstruointimenetelmän:
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;
}
Todella mielenkiintoinen osa - ja oikeastaan koko tämän viestin kohde (anteeksi sanapeli) - on SysExtensionAppClassFactory-luokan getClassFromSysAttribute()-metodi. Tämä menetelmä hyväksyy sen, että se hyväksyy hierarkian superluokan nimen (ja tämän superluokan ei tarvitse olla hierarkian huipulla ; se tarkoittaa yksinkertaisesti, että vain tätä luokkaa laajentavat luokat ovat kelvollisia) ja attribuuttiobjektin.
Sitten se palauttaa luokan objektin, joka laajentaa määritettyä superluokkaa ja on koristeltu vastaavalla attribuutilla.
Voit luonnollisesti lisätä rakennusmenetelmään niin paljon vahvistusta tai logiikkaa kuin haluat, mutta tärkeä poiminta tässä on, että kun se on otettu käyttöön, sinun ei koskaan tarvitse muokata tätä menetelmää uudelleen. Voit lisätä alaluokkia hierarkiaan ja niin kauan kuin varmistat, että koristelet ne asianmukaisesti, konstruktiomenetelmä löytää ne, vaikka niitä ei ollut olemassa kirjoitettaessa.
Entä suorituskyky? Rehellisesti sanottuna en ole yrittänyt vertailla sitä, mutta sisäinen tunne on, että tämä toimii luultavasti huonommin kuin klassinen kytkinlausekesuunnittelu. Ottaen kuitenkin huomioon, että ylivoimaisesti useimmat Dynamics AX:n suorituskykyongelmat johtuvat tietokannan käytöstä, en olisi siitä liikaa huolissani.
Tietysti, jos toteutat jotain, joka vaatii tuhansien objektien nopean luomisen, saatat haluta tutkia asiaa tarkemmin, mutta klassisissa tapauksissa, joissa vain instantoit yksittäistä objektia pitkää käsittelyä varten, epäilen, että sillä on merkitystä. Vianetsintävinkkini (seuraava kappale) huomioon ottaen näyttää myös siltä, että SysExtension-kehys perustuu välimuistiin, joten epäilen, että sillä ei ole merkittävää suorituskykyä heikentyneessä järjestelmässä. Vianetsintä: Jos rakennusmenetelmä ei löydä alaluokkiasi, vaikka olet varma, että ne on sisustettu oikein, se voi olla välimuistiongelma. Yritä tyhjentää sekä asiakkaan että palvelimen välimuistit. AOS:n ei pitäisi olla tarpeen käynnistää uudelleen, mutta se voi olla viimeinen keino.