Embrace the extensions mindset with Dynamics 365 for Finance and Operations
Original post:
https://blogs.msdn.microsoft.com/axinthefield/embrace-the-extensions-mindset-with-dynamics-365-for-finance-and-operations/
Scenario 1: Create a number sequence in a standard module
This is a common scenario and the good news is that it has barely changed from Dynamics AX 2012. In our example, we will add a new number sequence to the Accounts Receivables module (Customers) to provide new values for the custom MSVRMInsuranceProviderId EDT. To accomplish that, we need to make some small changes (plenty of examples of AX 2012 code available out there):- Add a new code block to the loadModule in the NumberSeqModuleXXX class of our module. I.e.: NumberSeqModuleCust.
- Add a new static method to the Parameters table of the module to get the number sequence reference, CustParameters in my example. This is not mandatory, though a best practice.
Let's create a new class in an extension model with the following code:
[ExtensionOf(classStr(NumberSeqModuleCustomer))] final class NumberSeqModuleCustMSVRM_Extension { protected void loadModule() { NumberSeqDatatype datatype = NumberSeqDatatype::construct(); next loadModule(); // Execute the augmented original class method /* Insurance Provider Id */ datatype.parmDatatypeId(extendedTypeNum(MSVRMInsuranceProviderId)); datatype.parmReferenceHelp(literalStr('Provider ID')); datatype.parmWizardIsContinuous(false); datatype.parmWizardIsManual(NoYes::No); datatype.parmWizardIsChangeDownAllowed(NoYes::No); datatype.parmWizardIsChangeUpAllowed(NoYes::No); datatype.parmSortField(1); datatype.addParameterType(NumberSeqParameterType::DataArea, true, false); this.create(datatype); } }This is a regular class extension like the ones we are working with since the beginnings of Dynamics 365. The most important parts of the code are marked in bold:
- _Extension suffix in the class name. This is mandatory as per .NET standards.
- ExtensionOf attribute tells the compiler which class we are extending.
- next call. This is the new thing I wanted to show. It allows us to call the same method in the class we are extending from. It can be confused with a super() call, but it's not the same as we don't have any inheritance here neither we know how many extensions this same class may have implemented in different modules. The latter is important as -same with event handlers- we cannot count on the execution order here.

Next step is to add the static method that will return the number sequence reference. It is kind of a Best Practice (BP) to add this method to the module's parameters table (CustParameters in my example). In Dynamics AX 2012 there was an accepted exception for this BP where sometimes these methods were created in a custom table (like the parameters table in our own module) to avoid over-layering a standard table just for this small change. Not a problem anymore.
We can create a table extension class to add the static method to the standard table without over-layering:
[ExtensionOf(tableStr(CustParameters))] final class CustParametersMSVRM_Extension { client server static NumberSequenceReference numRefMSVRMInsuranceProviderId() { return NumberSeqReference::findReference(extendedTypeNum(MSVRMInsuranceProviderId)); } }Of course, as extensions are strongly typed augmentations of classes, we have IntelliSense over the new methods, as they are in fact part of the final version of the class (called: effective class):

Scenario 2: Create a number sequence in a new module
Now just imagine you want to create the same number sequence as in the previous scenario but by creating your own module. Required steps are well known:- Add a new element to the NumberSeqModule base enum.
- Create a NumberSeqModule* class for our module.
- Let the system know our module exists.
NOTE: Use the "e:" or "c:" filter strings in the object designer to see only e:xtended or c:ustomized elements, as shown in the screenshot.
Now we need to create a new class (a completely new class, no extensions here as it's a new module, not an extension of an existing one) with the following code:/* Detailed description of how to setup references for number sequences can be found in method loadModule() on the superclass: NumberSeqApplicationModule. */ class NumberSeqModuleMSVRM extends NumberSeqApplicationModule { protected void loadModule() { NumberSeqDatatype datatype = NumberSeqDatatype::construct(); /* Insurance Provider Id */ datatype.parmDatatypeId(extendedTypeNum(MSVRMInsuranceProviderId)); datatype.parmReferenceHelp(literalStr('Provider ID')); datatype.parmWizardIsContinuous(false); datatype.parmWizardIsManual(NoYes::No); datatype.parmWizardIsChangeDownAllowed(NoYes::No); datatype.parmWizardIsChangeUpAllowed(NoYes::No); datatype.parmSortField(1); datatype.addParameterType(NumberSeqParameterType::DataArea, true, false); this.create(datatype); } public NumberSeqModule numberSeqModule() { return NumberSeqModule::MSVRM; } [SubscribesTo(classstr(NumberSeqGlobal),delegatestr(NumberSeqGlobal, buildModulesMapDelegate))] static void buildModulesMapSubsciber(Map numberSeqModuleNamesMap) { NumberSeqGlobal::addModuleToMap(classnum(NumberSeqModuleMSVRM), numberSeqModuleNamesMap); } }A subscription to the buildModuleMapDelegate delegate allows us to add our new module to the standard number sequences Map without any over-layering. A lot of new delegates have been added to the standard objects lately to allow more points where a subscription can be done to change the behavior of standard code. Look for them as this is the way developers tell others where to put their modifications.
If you're an ISV yourself, add delegates to your own code to allow others to extend your modules without over-layering. This will make life easier for every parties, as upgrading the ISV code will be possible without any code conflict.
If you feel that you have a business scenario that is impossible to achieve by using only extensions, please log an extension request explaining your case.
Take a look to my next blog post to continue on your Extensions journey: Embrace the extensions mindset with Dynamics 365 for Finance and Operations #2 – SysExtension framework
Comments
Post a Comment