Коришћење СисЕктенсион Фрамеворк-а да бисте сазнали коју подкласу треба инстанцирати у Динамицс АКС 2012
Објављено: 16. фебруар 2025. 00:29:31 UTC
Овај чланак описује како се користи мало познати оквир СисЕктенсион у Динамицс АКС 2012 и Динамицс 365 фор Оператионс за инстанцирање подкласа на основу декорација атрибута, омогућавајући лако проширив дизајн хијерархије класа обраде.
Using the SysExtension Framework to Find Out Which Subclass to Instantiate in Dynamics AX 2012
Информације у овом посту су засноване на Динамицс АКС 2012 Р3. Може, али и не мора бити важеће за друге верзије. (Ажурирање: могу да потврдим да информације у овом чланку важе и за Динамицс 365 фор Оператионс)
Када имплементирате класе за обраду у Динамицс АКС, често се суочавате са стварањем хијерархије класа у којој свака поткласа одговара набројаној вредности или има неку другу спрегу података. Класичан дизајн је да се затим у супер класи има конструктивни метод, који има прекидач који одређује коју класу треба инстанцирати на основу улаза.
Ово у принципу добро функционише, али ако имате много различитих могућих улаза (много елемената у енум-у или је можда улаз комбинација неколико различитих вредности), може постати заморно и подложно грешкама за одржавање, а дизајн увек има недостатак да ћете морати да модификујете поменуту методу конструкције ако икада додате нову подкласу или унесете измене у коју подкласу треба да се користи на основу тога.
На срећу, постоји много елегантнији, али нажалост и много мање познат начин да се то уради, наиме коришћењем СисЕктенсион оквира.
Овај оквир користи предности атрибута које можете користити да украсите своје подкласе да би систем могао да схвати која подкласа треба да се користи за руковање чиме. И даље ће вам требати конструктивни метод, али ако се уради исправно, никада нећете морати да га мењате када додајете нове подкласе.
Хајде да погледамо замишљен пример и кажемо да ћете имплементирати хијерархију која врши неку врсту обраде на основу табеле ИнвентТранс. Која ће се обрада обавити зависи од СтатусРецеипт и СтатусИссуе записа, као и од тога да ли су записи повезани са СалесЛине, ПурцхЛине или ниједном. Већ сада гледате у много различитих комбинација.
Рецимо онда да знате да за сада треба да рукујете само неколико комбинација, али такође знате да ће се од вас тражити да будете у стању да рукујете све више и више комбинација током времена.
Хајде да буде релативно једноставно и да кажемо да за сада треба да обрађујете само записе који се односе на СалесЛине са СтатусИссуе РесервПхисицал или РесервОрдеред, све остале комбинације се за сада могу занемарити, али пошто знате да ћете морати да рукујете њима касније, желећете да дизајнирате свој код на начин који га чини лако проширивим.
Ваша хијерархија за сада може изгледати отприлике овако:
- МиПроцессор
- МиПроцессор_Салес
- МиПроцессор_Салес_РесервОрдеред
- МиПроцессор_Салес_РесервПхисицал
- МиПроцессор_Салес
Сада можете лако имплементирати методу у супер класу која инстанцира подкласу засновану на МодулеИнвентПурцхСалес и СтатусИссуе енума. Али онда ћете морати да модификујете супер класу сваки пут када додате подкласу, а то заправо није идеја наслеђивања у објектно оријентисаном програмирању. На крају крајева, не морате да мењате РунБасеБатцх или СисОператионСервицеБасе сваки пут када додате нови пакетни посао.
Уместо тога, можете користити СисЕктенсион оквир. То ће захтевати да додате још једну класу, која треба да прошири СисАттрибуте. Ова класа ће се користити као атрибут којим можете украсити своје класе обраде.
Ова класа је веома слична ономе како бисте направили класу уговора података за имплементацију СисОператион, по томе што ће имати неке чланове података и парм методе за добијање и подешавање тих вредности.
У нашем случају, ЦлассДецларатион може изгледати отприлике овако:
{
ModuleInventPurchSales module;
StatusIssue statusIssue;
StatusReceipt statusReceipt
}
Морате да направите метод нев() за инстанцирање свих чланова података. Ако желите, можете дати неке или све од њих подразумеване вредности, али ја то нисам урадио.
StatusIssue _statusIssue,
StatusReceipt _statusReceipt)
{
;
super();
module = _module;
statusIssue = _statusIssue;
statusReceipt = _statusReceipt;
}
Такође би требало да примените метод парм за сваког члана података, али сам их овде изоставио јер сам сигуран да знате како то да урадите - у супротном, хајде да то сматрамо вежбом ;-)
Сада можете користити своју класу атрибута да украсите сваку од ваших класа обраде. На пример, декларације класе могу изгледати овако:
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
{
}
Наравно, можете именовати своје класе како год желите, важан део овде је да своје класе украшавате атрибутима који одговарају врсти обраде коју обављају. (Али имајте на уму да постоје конвенције о именовању за хијерархије класа у Динамицс АКС и увек је добра идеја да их следите, ако је могуће).
Сада када сте украсили своје класе да бисте идентификовали коју врсту обраде свака од њих обавља, можете искористити предности СисЕктенсион оквира да инстанцирате објекте подкласа по потреби.
У вашу супер класу (МиПроцессор), можете додати конструктивни метод као што је овај:
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;
}
Заиста интересантан део – и заиста објекат (извините на игри речи) целе ове објаве – је метода гетЦлассФромСисАттрибуте() у класи СисЕктенсионАппЦлассФацтори. Оно што овај метод ради је да прихвата име супер класе хијерархије (а ова супер класа не мора да буде на врху хијерархије; то једноставно значи да ће само класе које проширују ову класу бити квалификоване) и објекат атрибута.
Затим враћа објекат класе који проширује наведену супер класу и украшен је одговарајућим атрибутом.
Очигледно можете додати онолико додатне валидације или логике методи конструкта колико желите, али важан закључак је да када се једном имплементира, више никада не бисте требали модификовати овај метод. Можете додати подкласе у хијерархију и све док се побринете да их украсите на одговарајући начин, метода конструисања ће их пронаћи иако нису постојале када је написана.
Шта је са перформансама? Искрено, нисам покушао да га мерим, али имам осећај да ово вероватно ради лошије од класичног дизајна изјаве прекидача. Међутим, с обзиром на то да је далеко највише проблема са перформансама у Динамицс АКС узроковано приступом бази података, не бих превише бринуо о томе.
Наравно, ако имплементирате нешто што ће захтевати да се хиљаде објеката брзо креира, можда ћете желети да истражите даље, али у класичним случајевима где само инстанцирате један објекат да бисте обавили неку дуготрајну обраду, сумњам да ће то бити важно. Такође, узимајући у обзир мој савет за решавање проблема (следећи пасус), чини се да се оквир СисЕктенсион ослања на кеширање, тако да у систему који ради сумњам да има значајан ударац у перформансама. Решавање проблема: Ако метода конструисања не пронађе ваше подкласе иако сте сигурни да су правилно уређене, можда је проблем са кеширањем. Покушајте да обришете кеш и на клијенту и на серверу. Не би требало да буде потребно да поново покренете АОС, али то може бити последње решење.