Miklix

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

Објавено: 5 март 2025, во 19:54:40 UTC
Последно ажурирано: 12 јануари 2026, во 08:43:53 UTC

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


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

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 или има некое друго поврзување на податоци. Класичен дизајн е потоа да се има метод на конструкција во супер класата, кој има прекинувач кој одредува која класа да се инстанцира врз основа на влезот.

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

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

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

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

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

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

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

  • MyProcessorMyProcessor_SalesMyProcessor_Sales_ReservНарачаноMyProcessor_Sales_ReservФизички

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

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

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

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

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

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

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

    super();

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

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

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

[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 години искуство како професионален компјутерски програмер/развивач на софтвер и моментално е вработен со полно работно време во голема европска ИТ корпорација. Кога не пишува блог, тој го поминува своето слободно време на широк спектар на интереси, хоби и активности, кои до одреден степен може да се рефлектираат во разновидните теми опфатени на оваа веб-локација.