Miklix

SysExtension Frameworkin käyttäminen Dynamics AX 2012:ssa luotavan alaluokan selvittämiseen

Julkaistu: 16. helmikuuta 2025 klo 0.25.40 UTC
Viimeksi päivitetty: 12. tammikuuta 2026 klo 8.42.58 UTC

Tässä artikkelissa kuvataan, miten Dynamics AX 2012:n ja Dynamics 365 for Operationsin vähän tunnettua SysExtension-kehystä käytetään attribuuttikoristeluihin perustuvien alakategorioiden luomiseen, mikä mahdollistaa käsittelyluokkahierarkian helposti laajennettavan suunnittelun.


Tämä sivu on käännetty koneellisesti englannista, jotta se olisi mahdollisimman monen ihmisen saatavilla. Valitettavasti konekääntäminen ei ole vielä täydellistä tekniikkaa, joten virheitä voi esiintyä. Voit halutessasi tarkastella alkuperäistä englanninkielistä versiota täällä:

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. Ne eivät välttämättä päde muihin versioihin. (Päivitys: Voin vahvistaa, että tämän artikkelin tiedot pätevät myös Dynamics 365 for Operationsille.)

Kun toteutat prosessointiluokkia Dynamics AX:ssä, kohtaat usein luokkahierarkian luomisen, jossa jokainen aliluokka vastaa luetteloarvoa tai sillä on jokin muu datakytkentä. Klassinen suunnittelutapa on sitten sisällyttää construct-metodi superluokkaan, jossa on kytkin, joka määrittää, mikä luokka luodaan syötteen perusteella.

Tämä toimii periaatteessa hyvin, mutta jos sinulla on useita erilaisia mahdollisia syötteitä (useita elementtejä enumissa tai ehkä syöte on useiden eri arvojen yhdistelmä), sen ylläpito voi olla työlästä ja virhealtista. Suunnittelulla on aina se haittapuoli, että joudut muokkaamaan kyseistä rakennusmenetelmää, jos koskaan lisäät uuden alaluokan tai teet muutoksia siihen, mitä alaluokkaa tulisi käyttää minkäkin syötteen perusteella.

Onneksi on olemassa paljon tyylikkäämpi, mutta valitettavasti myös paljon vähemmän tunnettu tapa tehdä tämä, nimittäin SysExtension-kehyksen avulla.

Tämä viitekehys hyödyntää attribuutteja, joita voit käyttää alakategorioidesi koristeluun, jotta järjestelmä pystyy selvittämään, mitä alaluokkaa tulisi käyttää minkäkin käsittelyyn. Tarvitset silti konstruktiomenetelmän, mutta jos se tehdään oikein, sinun ei koskaan tarvitse muokata sitä uusia alakategorioita lisätessäsi.

Tarkastellaan kuvitteellista esimerkkiä, jossa aiot toteuttaa hierarkian, joka suorittaa jonkinlaista käsittelyä InventTrans-taulukon perusteella. Suoritettava käsittely riippuu tietueiden StatusReceipt- ja StatusIssue-arvoista sekä siitä, liittyvätkö tietueet SalesLine-, PurchLine- vai kumpaankaan. Jo nyt tarkastellaan monia erilaisia yhdistelmiä.

Oletetaan sitten, että tiedät, että tällä hetkellä sinun tarvitsee käsitellä vain kourallista yhdistelmiä, mutta tiedät myös, että sinulta pyydetään kykyä käsitellä yhä useampia yhdistelmiä ajan myötä.

Pidetään se suhteellisen yksinkertaisena ja sanotaan, että nyt sinun tarvitsee käsitellä vain SalesLine-tietueita, joiden StatusIssue-arvo on ReservPhysical tai ReservOrdered. Kaikki muut yhdistelmät voidaan jättää huomiotta toistaiseksi, mutta koska tiedät, että sinun on käsiteltävä niitä myöhemmin, sinun kannattaa suunnitella koodisi siten, että sitä on helppo laajentaa.

Hierarkiasi saattaa näyttää tällä hetkellä suunnilleen tältä:

  • OmaProsessoriOmaProsessori_MyyntiOmaProsessori_Myynti_VarausTilattuOmaProsessori_Myynti_VarausFyysinen

Nyt voisit helposti toteuttaa superluokassa metodin, joka luo aliluokan instanssin ModuleInventPurchSales- ja StatusIssue-enum-arvojen perusteella. Mutta silloin sinun on muokattava superluokkaa joka kerta, kun lisäät aliluokan, eikä se oikeastaan ole periytymisen idea olio-ohjelmoinnissa. Loppujen lopuksi sinun ei tarvitse muokata RunBaseBatch- tai SysOperationServiceBase-metodia joka kerta, kun lisäät uuden eräajon.

Sen sijaan voit käyttää SysExtension-kehystä. Se edellyttää toisen luokan lisäämistä, jonka on laajennettava SysAttribute-luokkaa. Tätä luokkaa käytetään attribuuttina, jolla voit koristella prosessointiluokkiasi.

Tämä luokka on hyvin samankaltainen kuin SysOperation-toteutuksen datasopimusluokan tekeminen siinä mielessä, että siinä on joitakin datajäseniä ja parm-metodeja näiden arvojen hakemiseen ja asettamiseen.

Meidän tapauksessamme luokkailmoitus voi näyttää suunnilleen tältä:

class MyProcessorSystemAttribute extends SysAttribute
{
    ModuleInventPurchSales  module;
    StatusIssue             statusIssue;
    StatusReceipt           statusReceipt
}

Sinun täytyy luoda new()-metodi kaikkien dataelementtien instanssien luomiseksi. Voit halutessasi antaa joillekin tai kaikille elementeille oletusarvot, mutta en ole tehnyt niin.

public void new(ModuleInventPurchSales  _module,
                StatusIssue             _statusIssue,
                StatusReceipt           _statusReceipt)
{
    ;

    super();

    module          = _module;
    statusIssue     = _statusIssue;
    statusReceipt   = _statusReceipt;
}

Ja sinun tulisi myös toteuttaa parm-metodi jokaiselle dataelementille, mutta olen jättänyt ne pois tästä, koska olen varma, että tiedät miten se tehdään - muuten pidetään sitä harjoituksena ;-)

Nyt voit käyttää attribuuttiluokkaasi koristellaksesi kutakin käsittelyluokkaasi. Esimerkiksi luokkamäärittelyt voisivat näyttää tältä:

[MyProcessorSystemAttribute(ModuleInventPurchSales::Sales,
                            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 tietenkin nimetä luokkiasi haluamallasi tavalla. Tärkeintä on, että lisäät luokkiisi määritteet, jotka vastaavat niiden suorittamaa prosessointia. (Muista kuitenkin, että Dynamics AX:ssä on luokkahierarkioille nimeämiskäytäntöjä, ja niitä on aina hyvä noudattaa, jos mahdollista.)

Nyt kun olet määrittänyt luokkiesi suoritustyypin ja määrittänyt, millaista prosessointia kukin luo, voit hyödyntää SysExtension-kehystä luodaksesi tarvittaessa avaluokkien objektien instansseja.

Superluokkaasi (MyProcessor) voisit lisätä seuraavanlaisen konstruktiomenetelmän:

public static MyProcessor construct(ModuleInventPurchSales _module,
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 objekti (anteeksi sanaleikki) – on SysExtensionAppClassFactory-luokan getClassFromSysAttribute()-metodi. Tämä metodi hyväksyy hierarkian superluokan nimen (eikä tämän superluokan tarvitse olla hierarkian huipulla; se tarkoittaa yksinkertaisesti sitä, 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 tietenkin lisätä construct-metodiin niin paljon validointia tai logiikkaa kuin haluat, mutta tärkein asia on, että kun metodi on kerran otettu käyttöön, sitä ei enää koskaan tarvitse muokata. Voit lisätä hierarkiaan alakategorioita, ja kunhan varmistat niiden asianmukaisen koristelun, construct-metodi löytää ne, vaikka niitä ei olisi ollut olemassa metodin kirjoitushetkellä.

Entä suorituskyky? En rehellisesti sanottuna ole yrittänyt vertailla sitä, mutta mutu-tuntemukseni on, että tämä toimii luultavasti huonommin kuin klassinen switch-lausesuunnittelu. Ottaen kuitenkin huomioon, että ylivoimaisesti suurin osa Dynamics AX:n suorituskykyongelmista johtuu tietokannan käytöstä, en olisi siitä liikaa huolissani.

Tietenkin, jos toteutat jotain, joka vaatii tuhansien objektien nopeaa luomista, kannattaa ehkä tutkia asiaa tarkemmin, mutta klassisissa tapauksissa, joissa vain luodaan yksi objekti pitkien käsittelyjen suorittamiseksi, epäilen, onko sillä merkitystä. Lisäksi, ottaen huomioon vianmääritysvihjeeni (seuraava kappale), näyttää siltä, että SysExtension-kehys perustuu välimuistiin, joten käynnissä olevassa järjestelmässä epäilen, että sillä olisi merkittävää suorituskyvyn heikkenemistä.

Vianmääritys: Jos construct-metodi ei löydä aliluokkiasi, vaikka olet varma, että ne on järjestetty oikein, kyseessä voi olla välimuistiongelma. Kokeile tyhjentää välimuistit sekä asiakasohjelmassa että palvelimella. AOS:n uudelleenkäynnistyksen ei pitäisi olla tarpeen, mutta se voi olla viimeinen keino.

Lisälukemista

Jos pidit tästä postauksesta, saatat pitää myös näistä ehdotuksista:


Jaa BlueskyssäJaa FacebookissaJaa LinkedInissäJaa TumblrissaJaa X:ssäJaa LinkedInissäPin Pinterestissä

Mikkel Christensen

Kirjoittajasta

Mikkel Christensen
Mikkel on miklix.com-sivuston luoja ja omistaja. Hänellä on yli 20 vuoden kokemus ammattimaisena tietokoneohjelmoijana/ohjelmistokehittäjänä, ja tällä hetkellä hän työskentelee kokopäiväisesti suuressa eurooppalaisessa IT-yrityksessä. Kun hän ei ole bloggaamassa, hän käyttää vapaa-aikaansa monenlaisiin kiinnostuksen kohteisiin, harrastuksiin ja aktiviteetteihin, mikä saattaa jossain määrin heijastua tällä verkkosivustolla käsiteltävien aiheiden moninaisuuteen.