Miklix

Ús del marc SysExtension per esbrinar quina subclasse s'ha d'instanciar al Dynamics AX 2012

Publicat: 5 de març del 2025, a les 19:30:27 UTC
Última actualització: 12 de gener del 2026, a les 8:43:51 UTC

Aquest article descriu com utilitzar el marc de treball poc conegut SysExtension al Dynamics AX 2012 i al Dynamics 365 for Operations per instanciar subclasses basades en decoracions d'atributs, cosa que permet un disseny fàcilment extensible d'una jerarquia de classes de processament.


Aquesta pàgina es va traduir automàticament de l'anglès per tal de fer-la accessible al màxim de persones possible. Malauradament, la traducció automàtica encara no és una tecnologia perfeccionada, de manera que es poden produir errors. Si ho prefereixes, pots veure la versió original en anglès aquí:

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

La informació d'aquesta publicació es basa en el Dynamics AX 2012 R3. Pot ser vàlida o no per a altres versions. (Actualització: puc confirmar que la informació d'aquest article també és vàlida per al Dynamics 365 for Operations)

Quan s'implementen classes de processament al Dynamics AX, sovint cal crear una jerarquia de classes en què cada subclasse correspon a un valor d'enumeració o té algun altre acoblament de dades. Un disseny clàssic és tenir un mètode de construcció a la superclasse, que té un interruptor que determina quina classe instanciar en funció de l'entrada.

En principi, això funciona bé, però si teniu moltes entrades possibles diferents (molts elements en una enumeració o potser l'entrada és una combinació de diversos valors diferents), pot arribar a ser tediós i propens a errors de mantenir, i el disseny sempre té el desavantatge que haureu de modificar aquest mètode de construcció si mai afegiu una nova subclasse o feu canvis a quina subclasse s'ha d'utilitzar en funció de quina entrada.

Afortunadament, hi ha una manera molt més elegant, però malauradament també molt menys coneguda, de fer-ho, concretament mitjançant l'ús del marc de treball SysExtension.

Aquest marc de treball aprofita els atributs que podeu utilitzar per decorar les vostres subclasses per tal que el sistema pugui esbrinar quina subclasse s'ha d'utilitzar per gestionar què. Tot i així, necessitareu un mètode de construcció, però si es fa correctament, no haureu de modificar-lo mai en afegir noves subclasses.

Vegem un exemple imaginari i suposem que implementareu una jerarquia que fa algun tipus de processament basat en la taula InventTrans. El processament a fer depèn de l'StatusReceipt i l'StatusIssue dels registres, així com de si els registres estan relacionats amb SalesLine, PurchLine o cap de les dues. Ara ja esteu veient moltes combinacions diferents.

Diguem aleshores que sabeu que ara només heu de gestionar un grapat de combinacions, però també sabeu que se us demanarà que pugueu gestionar cada cop més combinacions al llarg del temps.

Simplifiquem-ho relativament i diguem que, de moment, només cal gestionar els registres relacionats amb SalesLine amb un StatusIssue de ReservPhysical o ReservOrdered; totes les altres combinacions es poden ignorar de moment, però com que sabeu que les haureu de gestionar més endavant, voldreu dissenyar el codi de manera que sigui fàcilment extensible.

La teva jerarquia podria tenir un aspecte semblant a aquest, per ara:

  • ElMeuProcessadorElMeuProcessador_VendesElMeuProcessador_ReservaDemanatElMeuProcessador_Vendes_ReservaFísica

Ara, podríeu implementar fàcilment un mètode a la superclasse que instancia una subclasse basada en un ModuleInventPurchSales i un enum StatusIssue. Però aleshores haureu de modificar la superclasse cada vegada que afegiu una subclasse, i aquesta no és realment la idea d'herència en la programació orientada a objectes. Al cap i a la fi, no cal modificar RunBaseBatch o SysOperationServiceBase cada vegada que afegiu una nova tasca per lots.

En comptes d'això, podeu fer ús del marc de treball SysExtension. Això requerirà que afegiu una altra classe, que ha d'estendre SysAttribute. Aquesta classe s'utilitzarà com l'atribut amb què podeu decorar les vostres classes de processament.

Aquesta classe és molt similar a com es faria una classe de contracte de dades per a una implementació de SysOperation, ja que tindrà alguns membres de dades i mètodes parm per obtenir i definir aquests valors.

En el nostre cas, la ClassDeclaration podria tenir un aspecte semblant a aquest:

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

Cal crear un mètode new() per instanciar tots els membres de dades. Si voleu, podeu donar-los valors per defecte a alguns o a tots, però no ho he fet.

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

    super();

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

I també hauríeu d'implementar un mètode parm per a cada membre de dades, però els he omès aquí perquè estic segur que sabeu com fer-ho; si no, considerem-ho un exercici ;-)

Ara podeu utilitzar la vostra classe d'atributs per decorar cadascuna de les vostres classes de processament. Per exemple, les declaracions de classe podrien tenir aquest aspecte:

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

Per descomptat, podeu anomenar les vostres classes com vulgueu, però la part important aquí és que les decoreu amb atributs que corresponguin al tipus de processament que fan. (Però tingueu en compte que hi ha convencions de nomenclatura per a les jerarquies de classes al Dynamics AX i sempre és una bona idea seguir-les, si és possible).

Ara que heu decorat les vostres classes per identificar quin tipus de processament fa cadascuna d'elles, podeu aprofitar el marc de treball SysExtension per instanciar objectes de les subclasses segons calgui.

A la teva superclasse (MyProcessor), podries afegir un mètode de construcció com aquest:

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

La part realment interessant (i realment l'objectiu (perdoneu el joc de paraules) de tota aquesta publicació) és el mètode getClassFromSysAttribute() de la classe SysExtensionAppClassFactory. El que fa aquest mètode és acceptar el nom de la superclasse d'una jerarquia (i aquesta superclasse no necessita ser al capdamunt de la jerarquia; simplement significa que només les classes que estenen aquesta classe seran elegibles) i un objecte d'atribut.

Aleshores retorna un objecte d'una classe que estén la superclasse especificada i està decorat amb un atribut corresponent.

Evidentment, podeu afegir tanta validació o lògica addicional al mètode de construcció com vulgueu, però la conclusió important aquí és que, un cop implementat, no haureu de tornar a modificar aquest mètode. Podeu afegir subclasses a la jerarquia i, sempre que us assegureu de decorar-les adequadament, el mètode de construcció les trobarà encara que no existissin quan es va escriure.

Què passa amb el rendiment? Sincerament, no he intentat fer-ne una comparació, però tinc la sensació que probablement funciona pitjor que el disseny clàssic de les instruccions switch. Tanmateix, tenint en compte que, amb diferència, la majoria dels problemes de rendiment del Dynamics AX són causats per l'accés a la base de dades, no m'hi preocuparia gaire.

Per descomptat, si esteu implementant alguna cosa que requereixi la creació ràpida de milers d'objectes, potser voldreu investigar més a fons, però en els casos clàssics en què només instànciau un sol objecte per fer un processament llarg, dubto que importi. A més, tenint en compte el meu consell de resolució de problemes (següent paràgraf), sembla que el marc de treball SysExtension es basa en la memòria cau, de manera que en un sistema en execució dubto que tingui una disminució significativa del rendiment.

Resolució de problemes: Si el mètode de construcció no troba les subclasses tot i que esteu segurs que estan decorades correctament, pot ser un problema de memòria cau. Intenteu esborrar les memòries cau tant del client com del servidor. No hauria de ser necessari reiniciar l'AOS, però pot ser l'últim recurs.

Lectures addicionals

Si t'ha agradat aquesta publicació, també et poden agradar aquests suggeriments:


Comparteix a BlueskyComparteix a FacebookComparteix a LinkedInComparteix a TumblrComparteix a XComparteix a LinkedInPin a Pinterest

Mikkel Christensen

Sobre l'autor

Mikkel Christensen
Mikkel és el creador i propietari de miklix.com. Té més de 20 anys d'experiència com a programador/desenvolupador de programari informàtic professional i actualment treballa a temps complet per a una gran corporació informàtica europea. Quan no fa blocs, dedica el seu temps lliure a una gran varietat d'interessos, aficions i activitats, que fins a cert punt es poden reflectir en la varietat de temes tractats en aquest lloc web.