Користење на рамката 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 може да изгледа некако вака:
{
ModuleInventPurchSales module;
StatusIssue statusIssue;
StatusReceipt statusReceipt
}
Треба да направите new() метод за инстанцирање на сите членови на податоците. Ако сакате, можете да им дадете на некои или на сите нив стандардни вредности, но јас тоа не сум го направил.
StatusIssue _statusIssue,
StatusReceipt _statusReceipt)
{
;
super();
module = _module;
statusIssue = _statusIssue;
statusReceipt = _statusReceipt;
}
И треба да имплементирате и метод parm за секој член од податоците, но ги изоставив овде бидејќи сум сигурен дека знаете како да го направите тоа - во спротивно, ајде да го сметаме за вежба ;-)
Сега можете да ја користите вашата класа на атрибути за да ги декорирате сите ваши класи за обработка. На пример, декларациите на класите би можеле да изгледаат вака:
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), можете да додадете метод на конструкција како овој:
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, но тоа може да биде последно средство.
Дополнително читање
Ако ви се допадна овој пост, можеби ќе ви се допаднат и овие предлози:
- Претворете реално во стринг со сите децимали во Dynamics AX 2012
- Користење на барање во класа на договор за SysOperation податоци во Dynamics AX 2012
- Грешка „Нема дефинирана класа на метаподатоци за објект на договор за податоци“ во Dynamics AX 2012
