Miklix

Gebruik die SysExtension-raamwerk om uit te vind watter subklas in Dynamics AX 2012 geïnstalleer moet word

Gepubliseer: 16 Februarie 2025 om 00:26:31 UTC
Laas opgedateer: 12 Januarie 2026 om 08:43:38 UTC

Hierdie artikel beskryf hoe om die minder bekende SysExtension-raamwerk in Dynamics AX 2012 en Dynamics 365 for Operations te gebruik om subklasse gebaseer op attribuutversierings te instansieer, wat 'n maklik uitbreibare ontwerp van 'n verwerkingsklashiërargie moontlik maak.


Hierdie bladsy is masjienvertaal uit Engels om dit vir soveel mense moontlik toeganklik te maak. Ongelukkig is masjienvertaling nog nie 'n volmaakte tegnologie nie, dus kan foute voorkom. As jy verkies, kan jy die oorspronklike Engelse weergawe hier sien:

Using the SysExtension Framework to Find Out Which Subclass to Instantiate in Dynamics AX 2012

Die inligting in hierdie plasing is gebaseer op Dynamics AX 2012 R3. Dit mag dalk geldig wees vir ander weergawes, maar ook nie. (Opdatering: Ek kan bevestig dat die inligting in hierdie artikel ook geldig is vir Dynamics 365 for Operations)

Wanneer verwerkingsklasse in Dynamics AX geïmplementeer word, word jy dikwels gekonfronteer met die skep van 'n klashiërargie waarin elke subklas ooreenstem met 'n enum-waarde of 'n ander datakoppeling het. 'n Klassieke ontwerp is om dan 'n konstrukmetode in die superklas te hê, wat 'n skakelaar het wat bepaal watter klas geïnstansieer moet word gebaseer op die invoer.

Dit werk in beginsel goed, maar as jy baie verskillende moontlike insette het (baie elemente in 'n enum of miskien is die invoer 'n kombinasie van verskeie verskillende waardes), kan dit vervelig en foutgevoelig raak om te onderhou en die ontwerp het altyd die nadeel dat jy die konstruksiemetode sal moet wysig as jy ooit 'n nuwe subklas byvoeg of veranderinge maak aan watter subklas gebruik moet word gebaseer op watter invoer.

Gelukkig is daar 'n baie meer elegante, maar ongelukkig ook baie minder bekende, manier om dit te doen, naamlik deur die gebruik van die SysExtension-raamwerk.

Hierdie raamwerk maak gebruik van eienskappe wat jy kan gebruik om jou subklasse te versier sodat die stelsel kan uitvind watter subklas gebruik moet word om wat te hanteer. Jy sal steeds 'n konstrukmetode benodig, maar as dit korrek gedoen word, sal jy dit nooit hoef te wysig wanneer jy nuwe subklasse byvoeg nie.

Kom ons kyk na 'n denkbeeldige voorbeeld en sê dat jy 'n hiërargie gaan implementeer wat 'n soort verwerking doen gebaseer op die InventTrans-tabel. Watter verwerking om te doen hang af van die StatusReceipt en StatusIssue van die rekords, asook of die rekords verband hou met SalesLine, PurchLine of nie een van die twee nie. Jy kyk nou reeds na baie verskillende kombinasies.

Kom ons sê dan dat jy weet dat jy vir nou net 'n handjievol van die kombinasies hoef te hanteer, maar jy weet ook dat jy gevra sal word om mettertyd meer en meer kombinasies te kan hanteer.

Kom ons hou dit relatief eenvoudig en sê dat jy vir nou slegs rekords hoef te hanteer wat verband hou met SalesLine met 'n StatusIssue van ReservPhysical of ReservOrdered. Alle ander kombinasies kan vir nou geïgnoreer word, maar aangesien jy weet dat jy dit later sal moet hanteer, sal jy jou kode op 'n manier wil ontwerp wat dit maklik uitbreidbaar maak.

Jou hiërargie mag dalk vir nou so lyk:

  • MyVerwerkerMyVerwerker_VerkopeMyVerwerker_Verkope_BestelMyVerwerker_Verkope_BestelFisies

Nou kan jy maklik 'n metode in die superklas implementeer wat 'n subklas instansieer gebaseer op 'n ModuleInventPurchSales en 'n StatusIssue enum. Maar jy sal dan die superklas elke keer moet wysig wanneer jy 'n subklas byvoeg, en dit is nie regtig die idee van oorerwing in objekgeoriënteerde programmering nie. Jy hoef immers nie RunBaseBatch of SysOperationServiceBase elke keer te wysig wanneer jy 'n nuwe bondeltaak byvoeg nie.

In plaas daarvan kan jy die SysExtension-raamwerk gebruik. Dit sal vereis dat jy nog 'n klas byvoeg wat SysAttribute moet uitbrei. Hierdie klas sal gebruik word as die attribuut waarmee jy jou verwerkingsklasse kan versier.

Hierdie klas is baie soortgelyk aan hoe jy 'n datakontrakklas vir 'n SysOperation-implementering sou maak, aangesien dit 'n paar data-lede en parm-metodes sal hê om daardie waardes te kry en in te stel.

In ons geval kan die Klasverklaring so iets lyk:

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

Jy moet 'n new() metode maak om alle data-lede te instansieer. As jy wil, kan jy sommige of almal van hulle standaardwaardes gee, maar ek het dit nog nie gedoen nie.

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

    super();

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

En jy moet ook 'n parm-metode vir elke datalid implementeer, maar ek het dit hier weggelaat, want ek is seker jy weet hoe om dit te doen - andersins, kom ons beskou dit as 'n oefening ;-)

Nou kan jy jou attribuutklas gebruik om elk van jou verwerkingsklasse te versier. Byvoorbeeld, die klasverklarings kan so lyk:

[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
{
}

Jy kan natuurlik jou klasse enige naam gee wat jy wil, die belangrike deel hier is dat jy jou klasse versier met eienskappe wat ooreenstem met die soort verwerking wat hulle doen. (Maar hou in gedagte dat daar naamgewingskonvensies vir klashiërargieë in Dynamics AX is en dit is altyd 'n goeie idee om dit te volg, indien moontlik).

Noudat jy jou klasse versier het om te identifiseer watter soort verwerking elkeen van hulle doen, kan jy voordeel trek uit die SysExtension-raamwerk om objekte van die subklasse te instansieer soos nodig.

In jou superklas (MyProcessor), kan jy 'n konstrukmetode soos hierdie byvoeg:

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;
}

Die werklik interessante deel – en eintlik die objek (verskoon my woordspeling) van hierdie hele plasing – is die getClassFromSysAttribute() metode in die SysExtensionAppClassFactory klas. Wat hierdie metode doen, is dat dit die naam van die superklas van 'n hiërargie aanvaar (en hierdie superklas hoef nie bo-aan die hiërargie te wees nie; dit beteken eenvoudig dat slegs klasse wat hierdie klas uitbrei, in aanmerking sal kom) en 'n attribuutobjek.

Dit gee dan 'n voorwerp van 'n klas terug wat die gespesifiseerde superklas uitbrei en met 'n ooreenstemmende attribuut versier is.

Jy kan natuurlik soveel verdere validering of logika by die konstrukmetode voeg as wat jy wil, maar die belangrike les hier is dat sodra dit geïmplementeer is, jy hierdie metode nooit weer hoef te wysig nie. Jy kan subklasse by die hiërargie voeg en solank jy seker maak dat jy hulle toepaslik versier, sal die konstrukmetode hulle vind, al het hulle nie bestaan toe dit geskryf is nie.

Wat van werkverrigting? Ek het eerlikwaar nog nie probeer om dit te meet nie, maar my gevoel is dat dit waarskynlik swakker presteer as die klassieke skakelaar-stellingontwerp. Aangesien die meeste werkverrigtingsprobleme in Dynamics AX egter deur databasistoegang veroorsaak word, sou ek my nie te veel daaroor bekommer nie.

Natuurlik, as jy iets implementeer wat vereis dat duisende objekte vinnig geskep moet word, wil jy dalk verder ondersoek instel, maar in die klassieke gevalle waar jy net 'n enkele objek instansieer om langdurige verwerking te doen, twyfel ek of dit saak sal maak. Ook, as ek my probleemoplossingswenk (volgende paragraaf) in ag neem, blyk dit dat die SysExtension-raamwerk op kasgeheue staatmaak, so in 'n lopende stelsel twyfel ek of dit 'n beduidende prestasie-nederlaag het.

Probleemoplossing: As die konstruksiemetode nie jou subklasse vind nie, al is jy seker dat hulle korrek versier is, kan dit 'n kasprobleem wees. Probeer om kasgeheue op beide die kliënt en bediener skoon te maak. Dit behoort nie nodig te wees om die AOS te herbegin nie, maar dit kan 'n laaste uitweg wees.

Verdere Leeswerk

As jy hierdie plasing geniet het, sal jy dalk ook van hierdie voorstelle hou:


Deel op BlueskyDeel op FacebookDeel op LinkedInDeel op TumblrDeel op XDeel op LinkedInSpeld op Pinterest

Mikkel Christensen

Oor die skrywer

Mikkel Christensen
Mikkel is die skepper en eienaar van miklix.com. Hy het meer as 20 jaar ondervinding as 'n professionele rekenaarprogrammeerder/sagteware-ontwikkelaar en is tans voltyds in diens van 'n groot Europese IT-korporasie. Wanneer hy nie blog nie, spandeer hy sy vrye tyd aan 'n groot verskeidenheid belangstellings, stokperdjies en aktiwiteite, wat tot 'n mate weerspieël kan word in die verskeidenheid onderwerpe wat op hierdie webwerf gedek word.