Miklix

Користење на рамката SysExtension за да откриете која подкласа да се инстанцира во Dynamics AX 2012

Објавено: 5 март 2025, во 19:54:40 UTC

Оваа статија опишува како да се користи малку познатата рамка SysExtension во Dynamics AX 2012 и Dynamics 365 за операции за инстанцирање на подкласи засновани на украси на атрибути, овозможувајќи лесно проширување на дизајнот на хиерархија на класата за обработка.


Оваа страница беше машински преведена од англиски за да биде достапна за што повеќе луѓе. За жал, машинското преведување сè уште не е усовршена технологија, така што може да се појават грешки. Ако сакате, можете да ја видите оригиналната англиска верзија овде:

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

Информациите во овој пост се засноваат на Dynamics AX 2012 R3. Може или не може да важи за други верзии. (Ажурирање: можам да потврдам дека информациите во оваа статија важат и за Dynamics 365 for Operations)

Кога имплементирате класи за обработка во Dynamics AX, честопати се соочувате со создавање хиерархија на класи во која секоја подкласа одговара на вредност enum или има некоја друга спојка на податоци. Класичен дизајн е потоа да се има конструктивен метод во супер класата, кој има прекинувач кој одредува која класа да се инстанцира врз основа на влезот.

Ова функционира добро во принцип, но ако имате многу различни можни влезови (многу елементи во нумери или можеби влезот е комбинација од неколку различни вредности), може да стане досадно и склоно кон грешки за одржување и дизајнот секогаш има недостаток што ќе треба да го измените споменатиот метод на конструкција ако некогаш додадете нова подкласа или направите промени на која подкласа треба да се користи.

За среќа, постои многу поелегантен, но, за жал, и многу помалку познат начин за тоа, имено со користење на рамката SysExtension.

Оваа рамка ги користи предностите на атрибутите што можете да ги користите за да ги декорирате вашите подкласи за да го направи системот способен да открие која подкласа треба да се користи за ракување со што. Сè уште ќе ви треба конструктивен метод, но ако се направи правилно, никогаш нема да мора да го менувате кога додавате нови подкласи.

Ајде да погледнеме имагинарен пример и да кажеме дека ќе имплементирате хиерархија која прави некој вид на обработка врз основа на табелата InventTrans. Која обработка да се направи зависи од Status Receipt и StatusIssue на записите, како и од тоа дали записите се поврзани со SalesLine, PurchLine или ниту една друга. Веќе сега, гледате многу различни комбинации.

Да речеме тогаш дека знаете дека засега треба да се справите само со неколку комбинации, но исто така знаете дека од вас ќе биде побарано да можете да се справите со се повеќе и повеќе комбинации со текот на времето.

Да бидеме релативно едноставно и да кажеме дека засега треба само да ракувате со записите поврзани со SalesLine со StatusIssue of ReservPhysical или ReservOrdered, сите други комбинации засега може да се игнорираат, но бидејќи знаете дека ќе мора да ракувате со нив подоцна, ќе сакате да го дизајнирате вашиот код на начин што го прави лесно проширлив.

Вашата хиерархија засега може да изгледа вака:

  • MyProcessor
    • MyProcessor_Sales
      • MyProcessor_Sales_Reserved Ordered
      • MyProcessor_Sales_ReservPhysical

Сега, можете лесно да имплементирате метод во супер класата што инстанцира подкласа заснована на ModuleInventPurchSales и број StatusIssue. Но, тогаш ќе треба да ја менувате супер класата секогаш кога ќе додавате подкласа, а тоа всушност не е идејата за наследување во објектно-ориентираното програмирање. На крајот на краиштата, не треба да менувате RunBaseBatch или SysOperationServiceBase секој пат кога додавате нова серија работа.

Наместо тоа, можете да ја користите рамката SysExtension. Тоа ќе бара од вас да додадете друга класа, која треба да го прошири SysAttribute. Оваа класа ќе се користи како атрибут со кој можете да ги декорирате вашите класи за обработка.

Оваа класа е многу слична на тоа како би направиле класа за договор за податоци за имплементација на SysOperation, со тоа што ќе има некои членови на податоци и методи на парм за добивање и поставување на тие вредности.

Во нашиот случај, ClassDeclaration може да изгледа вака:

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

Треба да направите нов() метод за инстантирање на сите членови на податоци. Ако сакате, можете да дадете некои или сите стандардни вредности, но јас не го направив тоа.

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

    super();

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

И, исто така, треба да имплементирате парм метод за секој член на податоци, но јас ги испуштив оние овде бидејќи сум сигурен дека знаете како да го направите тоа - инаку, да го сметаме за вежба ;-)

Сега можете да ја користите вашата класа на атрибути за да ја декорирате секоја ваша класа за обработка. На пример, декларациите за класи може да изгледаат вака:

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

Се разбира, можете да ги именувате вашите часови како што сакате, важен дел овде е што ги декорирате вашите часови со атрибути кои одговараат на тоа каква обработка прават. (Но, имајте на ум дека постојат конвенции за именување за хиерархиите на класите во Dynamics AX и секогаш е добра идеја да ги следите, ако е можно).

Сега кога сте ги украсиле вашите класи за да идентификувате каква обработка прави секоја од нив, можете да ги искористите предностите на рамката SysExtension за да ги инстанцирате објектите од подкласите по потреба.

Во вашата супер класа (MyProcessor), можете да додадете конструктивен метод како овој:

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

Навистина интересниот дел - и навистина објектот (извинете за игра на зборови) на целиот овој пост - е методот getClassFromSysAttribute() во класата SysExtensionAppClassFactory. Она што го прави овој метод е дека го прифаќа името на супер класата на хиерархијата (и оваа супер класа не треба да биде на врвот на хиерархијата; тоа едноставно значи дека само класите што ја прошируваат оваа класа ќе бидат подобни) и објект на атрибут.

Потоа враќа објект од класата што ја проширува наведената супер класа и е украсена со соодветен атрибут.

Очигледно можете да додадете онолку понатамошна валидација или логика на методот на конструкција колку што сакате, но важното нешто овде е што откако ќе се имплементира, никогаш повеќе не треба да го менувате овој метод. Можете да додавате подкласи во хиерархијата и сè додека се погрижите соодветно да ги декорирате, методот на конструкција ќе ги пронајде иако не постоеле кога е напишано.

Што е со перформансите? Искрено, не се обидов да го мерим, но моето чувство на стомакот е дека ова веројатно функционира полошо од класичниот дизајн на изјава за прекинувач. Сепак, имајќи предвид дека убедливо најголемите проблеми со перформансите во Dynamics AX се предизвикани од пристапот до базата на податоци, не би се грижам премногу за тоа.

Се разбира, ако имплементирате нешто што ќе бара илјадници објекти да се создадат брзо, можеби ќе сакате да истражите дополнително, но во класичните случаи кога само имплементирате еден објект за да направите долга обработка, се сомневам дека тоа ќе биде важно. Исто така, земајќи го предвид мојот совет за решавање проблеми (следниот пасус), се чини дека рамката SysExtension се потпира на кеширање, така што во системот што работи се сомневам дека има значителен удар во перформансите. Решавање проблеми: Ако методот на конструкција не ги пронајде вашите подкласи, иако сте сигурни дека се правилно украсени, можеби е проблем со кеширањето. Обидете се да ги исчистите кешот и на клиентот и на серверот. Не треба да е неопходно да се рестартира AOS, но тоа може да биде последно средство.

Споделете на BlueskyСподелете на ФејсбукСподелете на LinkedInСподелете на TumblrСподелете на XСподелете на LinkedInЗакачи на Pinterest

Микел Банг Кристенсен

За авторот

Микел Банг Кристенсен
Микел е креатор и сопственик на miklix.com. Тој има над 20 години искуство како професионален компјутерски програмер/развивач на софтвер и моментално е вработен со полно работно време во голема европска ИТ корпорација. Кога не пишува блог, тој го поминува своето слободно време на широк спектар на интереси, хоби и активности, кои до одреден степен може да се рефлектираат во разновидните теми опфатени на оваа веб-локација.