Professional Documents
Culture Documents
CHAPTER 3: CLASSES
Objectives
The objectives are:
Introduction
Microsoft Dynamics® AX provides a large range of standard system classes that
you can use while developing X++ code. This lesson introduces some of the most
commonly used system classes, and demonstrates ways they can be used to
support modifications.
3-1
Development III in Microsoft Dynamics® AX 2012
Collection Classes
X++ contains two compound data types: arrays and containers. They are useful
for aggregating values of simpler data types. However, you cannot store objects
in arrays or containers. The Microsoft Dynamics AX collection classes have been
designed for storing objects.
• List
• Map
• Set
• Array
• Struct
• RecordSortedList
• RecordInsertList
List
A List object contains members that are accessed sequentially. Lists are
structures that can contain members of any X++ type. All the members in the
same list must be of the same type.
The ListEnumerator class allows you to traverse through the elements within a
list. The following methods are commonly used on ListEnumerator objects:
3-2
Chapter 3: Classes
The following example demonstrates how to create a list, then move through it
and extract values from it.
1. Create a new List object, specifying the data type it will contain.
2. Add members to the List object, using the List.addEnd() and
List.addStart() methods.
3. Set the ListEnumerator object using the List.getEnumerator()
method.
4. Go to the start of the list, using ListEnumerator.reset().
5. Move through the members of the list, using
ListEnumerator.moveNext().
6. Pull the value of the current member in the list, using
ListEnumerator.current().
// Go to beginning of enumerator
enumerator.reset();
When the code is executed, the result in the infolog should be as follows:
• First element is 3
• Second element is 1
Map
A Map object associates one value (the key) with another value. Both the key
and value can be of any valid X++ type, including objects. The types of the key
and value are specified in the declaration of the map. The way in which maps are
implemented means that access to the values is very fast.
3-3
Development III in Microsoft Dynamics® AX 2012
Multiple keys can map to the same value, but one key can map to only one value
at a time. If a [key, value] pair is added where the key already exists, it will
replace the existing pair with that key value.
1. Create a new Map object, specifying the data type it will contain.
2. Loop through the records in the CustTable. For each, use
Map.exists() to check if CustTable.stateName() already exists as a
key in the map.
3. If it does not already exist, use Map.insert() to insert a pair of
(CustTable.stateName(), 1).
4. If it does already exist, use Map.insert() to re-insert the pair with the
same key (which will overwrite the existing pair), but the new value
equals the existing pair value plus 1.
5. Set the MapEnumerator object using the Map.getEnumerator()
method.
6. Go to the start of the map, using MapEnumerator.reset().
3-4
Chapter 3: Classes
Map mapStateNumbers;
MapEnumerator enumerator;
CustTable custTable;
enumerator = mapStateNumbers.getEnumerator();
while (enumerator.moveNext())
{
info(strfmt("%1 customers are located in %2.",
enumerator.currentValue(), enumerator.currentKey());
}
Set
A Set is used for the storage and retrieval of data from a collection in which the
members are unique. The values of the members serve as the key according to
which the data is automatically ordered. Thus, it differs from a List collection
class where the members are placed into a specific position, and not ordered
automatically by their value.
Set members may be of any X++ type. All members in the set must have the
same type.
When a value that is already stored in the set is added again, it is ignored and
does not increase the number of members in the set.
3-5
Development III in Microsoft Dynamics® AX 2012
The SetEnumerator class allows you to traverse through the members within a
set. The following methods are commonly used on SetEnumerator objects:
The following example demonstrates how to create two sets, and then compares
each set to detect any shared members and remove them.
1. Create two new Set objects, specifying the data type they will
contain.
2. Add members to the Set objects, using the Set.insert() method.
3. Set a SetEnumerator object for one of the Sets, using the
Set.getEnumerator() method.
4. Go to the start of the set, using SetEnumerator.reset().
5. Move through the members in the set, using
SetEnumerator.moveNext().
6. Pull the value of the current member in the set, using
SetEnumerator.current().
7. Search for the value in the second set, using Set.in(). If found,
remove it using Set.remove().
Set setOne;
Set setTwo;
SetEnumerator enumerator;
Int value;
enumerator = setOne.getEnumerator();
3-6
Chapter 3: Classes
while (enumerator.moveNext())
{
value = enumerator.current();
if (setTwo.in(value))
{
setTwo.remove(value);
}
}
Array
Array objects may hold values of any single type, including objects and records.
Objects of this type may be transferred to functions and methods. The values are
stored sequentially.
The following is an example using an Array object that holds three different
Query objects:
Struct
Struct objects (short for structures) are entities that can hold a number of values
of any X++ type. Structs are used to group information about a specific entity.
For example, there may be a need to store information about a customer's name,
group and address and then treat this compound information as one item.
3-7
Development III in Microsoft Dynamics® AX 2012
The fields in a struct are specified by a data type and a name. Fields can be
added when the struct is created by using the new() method, or they can be
created after the struct has been created using the add() method. If a field is
added using the add() method, the value is specified for the field at the same
time, and the data type is inferred from this value. If a field is added during the
instantiation of the struct, the value() or the valueIndex() method needs to be
used to assign a value to it.
The fields in a struct are arranged in alphabetical order of the field names.
• String : Group
• String : Name
• Integer : Shoesize
3-8
Chapter 3: Classes
RecordSortedList
The RecordSortedList class inserts multiple records in a single database trip,
and can hold a subset of data from a table in a particular sort order that does not
exist as an index.
A RecordSortedList object holds records from a single table. The list has a
unique key that is defined by the fields listed by using the sortOrder method.
Records are automatically sorted as they are inserted, they do not have to be
inserted in sort sequence.
• Are faster
• Are not disk-based
• Only have one index
• Cannot be used in forms
• Require a call between the client and server per (grouped) read
• del(common) - removes a record that has a key that matches the key
fields in the recordBuffer from the RecordSortedList.
• find(common) - sets the recordBuffer to the contents of the record
that has a key that matches the key fields in the recordBuffer, and
positions the list to the record returned.
• first() - positions the list to the first record in the list, and copies its
contents to the recordBuffer.
• ins(common) - inserts a new record in a RecordSortedList, unless it
is a duplicate.
• insertDatabase() - inserts multiple records on a single trip to the
database.
• len() - returns the current number of records in a RecordSortedList
object.
• next() - sets the record buffer to the contents of the next record in the
RecordSortedList and positions the list to the record returned.
3-9
Development III in Microsoft Dynamics® AX 2012
RecordSortedList recordSortedList;
CustTable custTable;
recordSortedList = new
RecordSortedList(tablenum(CustTable));
custTable.clear();
custTable.AccountNum = "123";
custTable.CustGroup = "DOM";
custTable.Currency = "USD";
recordSortedList.ins(custTable);
custTable.clear();
custTable.AccountNum = "456";
custTable.CustGroup = "DOM";
custTable.Currency = "USD";
recordSortedList.ins(custTable);
custTable.clear();
custTable.AccountNum ="789";
custTable.CustGroup ="INT";
custTable.Currency ="USD";
recordSortedList.ins(custTable);
recordSortedList.insertDatabase();
RecordInsertList
The RecordInsertList class provides array insert capabilities in the kernel. This
allows you to insert more than one record into the database at a time, which
reduces communication between the application and the database.
Records are inserted only when the kernel finds the time appropriate, but they are
inserted no later than the call to the add() and insertDatabase() methods. These
same methods also return the accumulated number of records that are currently
inserted, which allows you to keep track of when the records are actually
inserted.
3-10
Chapter 3: Classes
bomList.insertDatabase();
}
3-11
Development III in Microsoft Dynamics® AX 2012
Isaac, the Systems Developer, has been asked to create a function that will
quickly inform a user how many customers and vendors are located in each
country. This is a key business indicator for the company.
Challenge Yourself!
Make a map that holds a Country Name and a count of all Customers that have a
postal address in that Country. Enumerate through the map and print the result.
Create another method that will enumerate through the key\value pairs and
output both values to the infolog.
Create a method that will call both methods and a main method so that the class
can be called from a menu.
Step by Step
3-12
Chapter 3: Classes
cnt = 0;
if (countryMap.exists(countryName))
{
cnt = countryMap.lookup(countryName);
countryMap.remove(countryId);
}
cnt++;
countryMap.insert(countryName, cnt);
}
}
while (mapEnumerator.moveNext())
{
info(strFmt("There are %1 customers in %2",
mapEnumerator.currentValue(), mapEnumerator.currentKey()));
}
}
countryCount.run();
}
3-13
Development III in Microsoft Dynamics® AX 2012
These classes also enable you to create and modify application objects.
Form Classes
The Form classes enable you to manipulate, create, modify, or run forms by
using X++ code. You can also modify forms during run time so, for example, one
or more controls are hidden on a form, depending on the user's selections in the
preceding form.
The Form classes are all system classes and are prefixed with Form. For
example, FormRun, FormStringControl.
3-14
Chapter 3: Classes
The following example demonstrates how to create and then run a form using
X++ code:
3-15
Development III in Microsoft Dynamics® AX 2012
fbDS = form.addDataSource(dictTable.name());
fbDS.table(dictTable.id());
// Add tab
fbTab = fbDesign.addControl(fctTab, "Overview");
3-16
Chapter 3: Classes
fbTabPage2 = fbTab.addControl(fctTabPage,"General");
fbTabPage2.caption("General");
Query Classes
Query classes were introduced in "Chapter 2: Working with Data." This lesson
provides a demonstration using these classes.
This example demonstrates how to use the Query classes to build a query.
3-17
Development III in Microsoft Dynamics® AX 2012
qbds = query.addDataSource(TableNum(CustTable));
qbds.addOrderByField(FieldNum(CustTable, CustGroup));
qr = new QueryRun(query);
return qr;
}
3-18
Chapter 3: Classes
You have been asked to create a function that will quickly show the user a list of
items that have been sold on a sales order. This is a key business indicator for
your company.
Challenge Yourself!
Create methods that build and use a query to display data. It should prompt the
user for the sales order number and then list all item id's and item names of lines
on that sales order.
Step by Step
class SalesListItems
{
QueryRun queryRun;
}
dataSource = query.addDataSource(tableNum(SalesLine));
query.addQueryFilter(dataSource, fieldStr(SalesLine,
SalesId));
while (queryRun.next())
{
salesLine = queryRun.get(tableNum(SalesLine));
3-19
Development III in Microsoft Dynamics® AX 2012
info(strFmt("%1 %2",salesLine.ItemId,
salesLine.itemName()));
}
}
if (queryRun.prompt())
this.listItems();
}
3-20
Chapter 3: Classes
Most application substituted kernel classes have a global variable used to access
the class. The global variables do not need a variable declaration and are pre-
instantiated by the client.
Each class serves a different purpose. The extent to which you will need to use
them vary.
• Always use the application classes rather than using the system
classes directly.
• Use the global variables to access the classes, when available.
• Never instantiate these classes (except for the Session class). Use the
global variables listed below instead.
• Specify the application class name to access static methods.
xApplication
The xApplication class provides access to information about the current
application. It also provides some application level functions.
The Application class extends the xApplication class, and allows its methods to
be overridden.
3-21
Development III in Microsoft Dynamics® AX 2012
Some of the more commonly used and overridden methods on Application are:
xCompany
The xCompany class provides access to information about the current company
(dataArea). It also provides some application level functions.
The Company class extends the xCompany class, and allows its methods to be
overridden.
Some of the more commonly used and overridden methods on Company are:
xInfo
The xInfo class provides access to the InfoLog framework.
The Info class extends the xInfo class, and allows its methods to be overridden.
Some of the more commonly used and overridden methods on Info are:
xGlobal
The xGlobal class provides a large selection of functions, designed to be used
anywhere in the application.
The Global class extends the xGlobal class, and allows its methods to be
overridden, and for extra global methods to be created. Many of the methods on
Global provide useful data manipulation functions. (For example,
numeralsToTxt(), str2con(), utcDateTime2SystemDateTime()).
3-22
Chapter 3: Classes
The static methods on Global are special in that they can be called from any
place in the application, without having to specify the Global class. For example,
Global::time2StrHMS() can be called as time2StrHMS(). In this way, they
become more like the system functions.
xClassFactory
The xClassFactory class is used by the system to create objects from classes.
One analogy of this is, a Class is a blueprint, xClassFactory is a factory and an
Object is the finished product.
The ClassFactory class extends the xClassFactory class, and allows its methods
to be overridden.
The following example demonstrates how to use ClassFactory to create and run
the CustTable form using X++:
Args args;
FormRun formRun;
3-23
Development III in Microsoft Dynamics® AX 2012
Since your company's recent upgrade to Microsoft Dynamics AX 2012, there has
been a request for a function to convert a Date type value to an equivalent
utcDateTime type value. You have been given the task of creating a new function
to perform this conversion.
Challenge Yourself!
Create a global method which converts a date value to its equivalent
utcDateTime value. Write a method to accept a date value and set the time
component equal to midnight. Use the new global method to output the
utcDateTime of a specified date to the screen using a job.
Step by Step
3-24
Chapter 3: Classes
RunBase Framework
The functions in Microsoft Dynamics AX can be categorized into three basic
groups:
• Data entry/queries
• Reporting
• Data manipulation
The RunBase class is an abstract class which defines a common structure for all
data manipulation functions in Microsoft Dynamics AX. Using this framework
has the following advantages:
When building new operations that need to be used interactively and from batch,
the BOF should be used.
What's New: Services & AIF for Developers in Microsoft Dynamics AX 2012 -
http://go.microsoft.com/fwlink/?LinkID=224714&clcid=0x409
3-25
Development III in Microsoft Dynamics® AX 2012
• ClassDeclaration
• pack
• unpack
• run
• description (static)
• main (static)
• dialog
• getFromDialog
If the dialog methods are not overridden, this provides a standard blank dialog.
ClassDeclaration
The classDeclaration consists of three types of definitions:
CustAccount custAccount;
FromDate fromDate;
ToDate toDate;
#DEFINE.CurrentVersion(1)
#LOCALMACRO.CurrentList
custAccount,
3-26
Chapter 3: Classes
fromDate,
toDate
#ENDMACRO
}
The individual fields of the dialog will be initialized in the method dialog().
When the dialog is accepted by the user, the contents of the dialog fields are read
in the method getFromDialog(). As both methods have to access the same
variables, they are defined as members of the class.
The manipulation in the method run() uses the information from the dialog. This
information is stored in variables with specific data types. These variables are
initialized in the method getFromDialog() and read in the method run().
The information for the last used dialog values is packed into a container
structure. The variables that should be packed are defined in the CurrentList
macro in the classDeclaration.
Dialog
This method builds a dialog and initializes the fields that will be used to capture
data from the user. These variables can be automatically initialized with the same
data selected in the last run.
Typically, developers initialize the dialog object by a call to super() and then add
fields and other controls, afterward. The dialog() method for this example has the
following contents.
dialog = super();
dialogAccount =
dialog.addFieldValue(extendedTypeStr(CustAccount),
custAccount);
groupPeriod = dialog.addGroup("Period");
dialogFromDate =
dialog.addFieldValue(extendedTypeStr(FromDate), fromDate,
"Period from");
dialogToDate =
dialog.addFieldValue(extendedTypeStr(ToDate), toDate,
"Period to");
return dialog;
3-27
Development III in Microsoft Dynamics® AX 2012
Visual elements are added to the dialog design using the add*() methods on the
Dialog object. This code first adds one field of type CustAccount, and references
the custAccount variable (the value of which will be used as the default for the
field, if it has a value). Then, a group is added to the design, with a caption
"Period". The two fields added after that will be included in the just created
group (by default). These two fields also reference class variables, and include a
third text parameter to override the label on the fields.
GetFromDialog
This method is called immediately after the dialog is accepted by the user, and
before the run() method is called. It is used to transfer the information from the
dialog fields into the class variables.
ret = super();
custAccount = dialogAccount.value();
fromDate = dialogFromDate.value();
toDate = dialogToDate.value();
return ret;
}
3-28
Chapter 3: Classes
Pack
The task for this method is to return a container with the information. This can be
used to initialize a similar data manipulation on another computer and/or at
another time. The information packed should be sufficient to communicate
information from the dialog to the data manipulation in the run-method.
The container should contain a version number as the first element. This number
should control how the rest of the container is structured. If you change the
contents of the container, you should increment the version number.
The pack method frequently has the following basic contents. However, it cannot
be inherited as it contains references to macros defined locally in the class
declaration.
• To save and restore the dialog between each use of the class. The
information is usually saved on a per user/company basis.
• To save and restore the specification of the manipulation to execute
on a batch server.
• To transfer the object from the client to the server. This is done to
optimize both the user dialog and the data manipulation in an AOS
environment.
Unpack
The unpack() method is the counterpart to the pack() method. It receives a
container as a parameter and restores the type specific variables of the class. The
method returns a Boolean with the value true if the information could be restored.
The unpack() method handles the current version number as a minimum, which
is defined in the ClassDeclaration. You can select to support unpacking of older
versions by extending the switch statement.
switch (version)
{
case(#CurrentVersion) :
3-29
Development III in Microsoft Dynamics® AX 2012
[version,#CurrentList] = _packedClass;
break;
default :
return false;
}
return true;
}
Run
The run() method controls the data manipulation. The method can use the
variables defined in the classDeclaration and initialized from the dialog. The
method does not receive any formal parameters.
The content of the run() method is unique for each data manipulation, based on
requirements. It will typically contain some local variables and a "try-catch"
statement with TTS calls that wrap all physical data manipulation into one logical
transaction.
Description
The description() method returns a descriptive name for the data manipulation.
The value is used to identify the job in the batch queue and is used as the caption
in the dialog.
3-30
Chapter 3: Classes
This method is static, which means that it can be executed on the opposite tier of
the object. In this case, because the method does not contain user interface or
data interface, the specification of both client and server results in an execution
of the method on the tier it is called from regardless of the settings on the class
properties.
Main
The main() method is the entry point when the class is executed from a menu
item. The method is static. It defines and initializes the object. Notice that new()
should never accept any parameters. The main method receives one formal
parameter that is an args() object. This object is described further.
The main() method is also responsible for calling prompt(), which executes the
dialog, and then calling run() to perform the manipulation.
if (demoRunBase.prompt())
{
demoRunBase.run();
}
}
With a main() method in place, a RunBase class can now be called from a menu
item in the AOT.
If the previous example is changed to initialize, specify input for, and execute the
data manipulation without a dialog, it will require extra methods to set the type
specific variables.
3-31
Development III in Microsoft Dynamics® AX 2012
The following parm method can get or set the custAccount variable:
Parm methods would also be required for the toDate and fromDate variables.
The following illustrates how you can execute the class directly from X++,
instead of from a menu item.
custAccount = "4001";
fromDate = mkdate(1,1,2006);
toDate = mkdate(31,12,2006);
demoRunBase.parmCustAccount(custAccount);
demoRunBase.parmFromDate(fromDate);
demoRunBase.parmToDate(toDate);
demoRunBase.run();
}
This approach can also be used to transfer information from the main() method
to the object. If you combine a dialog with the above approach, call the method
getLast() on the RunBase object before activating the parm*() methods.
Otherwise, the prompt() method restores the choices from the last execution and
overwrites the initialization.
Integration of a Query
To incorporate a query into the dialog of a RunBase class, implement the
following methods and modifications. The following examples will replace the
CustAccount, FromDate and ToDate dialog fields, with a single query on the
CustTrans table, to allow the user to specify their own criteria.
3-32
Chapter 3: Classes
classDeclaration
#DEFINE.CurrentVersion(1)
#LOCALMACRO.CurrentList
#ENDMACRO
}
InitParmDefault
The RunBase framework calls the initParmDefault() method when initializing a
new object of a RunBase class, if the class does not have previous initialization
data stored in Usage data.
super();
dataSource = query.addDataSource(tableNum(CustTrans));
dataSource.addRange(fieldNum(CustTrans, AccountNum));
dataSource.addRange(fieldNum(CustTrans, TransDate));
If a class has data in Usage data, new objects are initialized with the unpack
method.
3-33
Development III in Microsoft Dynamics® AX 2012
QueryRun
The queryRun() method returns the handle to the queryRun. The method usually
resembles the following content.
ShowQueryValues
The showQueryValues() method indicates if the query should be active in the
dialog. If the user must access the query in the dialog, override this method and
return true.
This method should now include the information stored in the queryRun object.
Do this by adding the result of the queryRun.pack() method to the container:
When combining dialog fields with a query, the first container still contains the
#CurrentList macro:
The unpack() method re-initializes the queryRun object from the saved
information. Do this as shown by the following content.
switch (version)
{
3-34
Chapter 3: Classes
case #CurrentVersion:
[version, packedQuery] = _packedClass;
if (packedQuery)
{
queryRun = new QueryRun(packedQuery);
}
break;
default :
return false;
}
return true;
}
When combining dialog fields with a query, the unpack of the container contains
the #CurrentList macro.
Run
The run() method can use the queryRun object directly as it is initialized after
the user has accepted the dialog.
while (queryRun.next())
{
custTrans = queryRun.get(tableNum(CustTrans));
amountMST += custTrans.AmountMST;
}
3-35
Development III in Microsoft Dynamics® AX 2012
When this version of the class is run from a menu item, the dialog has the query
select button and criteria preview, as shown in the following figure:
3-36
Chapter 3: Classes
You have been asked to create a function that will quickly calculate the average
sales price of an item, between a range of dates. This is a key business indicator
for your company.
Challenge Yourself!
Make a new class called SalesCalcAverageSalesPrice, using the RunBase
framework. The class should prompt for an Item Number, and To and From
dates. The run() method should calculate the average sales price of all sales lines
for that Item, with order creation dates between the dialog To and From dates.
Put the result in the infolog.
Step by Step
dlgFromDate = dlg.addField(identifierStr(FromDate));
dlgToDate = dlg.addField(identifierStr(ToDate));
dlgItemId = dlg.addField(identifierStr(itemId));
return dlg;
}
3-37
Development III in Microsoft Dynamics® AX 2012
fromDate = dlgFromDate.value();
toDate = dlgToDate.value();
itemId = dlgItemId.value();
ret = super();
return ret;
}
if (custInvoiceTrans.Qty)
info(strFmt("Average sales price is %1",
custInvoiceTrans.SalesPrice / custInvoiceTrans.Qty));
else
info("No sales found");
if (SalesCalcAverageSalesPrice.prompt())
SalesCalcAverageSalesPrice.run();
}
3-38
Chapter 3: Classes
Args Object
The Args class defines information communicated between running application
objects. The application object that initiates the communication (the caller),
initializes an Args object containing some information and then passes it to the
application object that is being called.
Communication through the args object can occur automatically without any
X++ programming.
If the caller is activating the called object by a menu item the Args object is
automatically initialized and sent as a parameter to the object called. AOT
properties of the menu item will be used.
However, you can program one or both sides of the communication yourself.
3-39
Development III in Microsoft Dynamics® AX 2012
Object dialog()
{
Args args;
FormRun formRun;
mayBeExecuted = false;
args = new Args();
args.name(formStr(LedgerConsolidate));
args.caller(this);
formRun = ClassFactory::formRunClassOnClient(args);
formRun.init();
return formRun;
}
This code shows an example of how to replace a dialog object with a form from
the AOT, within the RunBase framework. The form called can access the
LedgerConsolidate class through args.caller(). This way, the form and class can
exchange information.
if (args.record())
{
switch (args.dataset())
{
case tablenum(BankChequeTable) :
chequeCancel =
BankChequeCancel::newBankChequeTable(args.record());
break;
default :
throw
error(strfmt("@SYS22828","@SYS22512"));
}
if (chequeCancel.prompt())
{
localArgs.caller(chequeCancel);
localArgs.record(args.record());
3-40
Chapter 3: Classes
BankChequeCancel::serverRun(localArgs);
}
}
}
Notice that this method also declares, initializes, and uses a local Args object for
calling the static method BankChequeCancel::serverRun().
3-41
Development III in Microsoft Dynamics® AX 2012
You have been asked to add the average sales price calculation to the Released
products form. The current item id in the form should be used for the item id in
the calculation
Challenge Yourself!
Modify the class SalesCalcAverageSalesPrice so when it is called with an active
InventTable record, the class should set the item id based on this record and not
prompt the user for the item id.
Step by Step
3-42
Chapter 3: Classes
if (_args.dataset() == tableNum(InventTable))
{
InventTable = _args.record();
SalesCalcAverageSalesPrice.parmItemId(InventTable.ItemId);
}
if (SalesCalcAverageSalesPrice.prompt())
SalesCalcAverageSalesPrice.run();
}
dlgFromDate = dlg.addField(identifierStr(FromDate));
dlgToDate = dlg.addField(identifierStr(ToDate));
if (!itemId)
dlgItemId = dlg.addField(identifierStr(itemId));
return dlg;
}
fromDate = dlgFromDate.value();
toDate = dlgToDate.value();
if (!itemId)
itemId = dlgItemId.value();
ret = super();
return ret;
}
3-43
Development III in Microsoft Dynamics® AX 2012
Summary
Using system classes in conjunction with your modifications will help leverage
existing frameworks, and access important system data, to ultimately provide a
richer and more consistent Microsoft Dynamics AX enhancement for end users.
3-44
Chapter 3: Classes
1. Which of the following are Collection classes? (Select all that apply)
( ) Struct
( ) Map
( ) Container
( ) List
2. What class is used to iterate through the elements stored in a Map object?
3-45
Development III in Microsoft Dynamics® AX 2012
7. Which method on Args should only be used when no other methods will
suffice?
( ) parm()
( ) parmEnum()
( ) parmEnumType()
( ) record()
3-46
Chapter 3: Classes
1.
2.
3.
3-47
Development III in Microsoft Dynamics® AX 2012
Solutions
Test Your Knowledge
1. Which of the following are Collection classes? (Select all that apply)
(√) Struct
(√) Map
( ) Container
(√) List
2. What class is used to iterate through the elements stored in a Map object?
MODEL ANSWER:
MapEnumerator.
MapIterator is also correct, but a secondary choice.
3-48
Chapter 3: Classes
MODEL ANSWER:
Given a reference to a form in the AOT, this method will return a FormRun
object, which is a runnable form object.
MODEL ANSWER:
To save and restore user input and to transfer the object from the client to the
server.
7. Which method on Args should only be used when no other methods will
suffice?
(•) parm()
( ) parmEnum()
( ) parmEnumType()
( ) record()
3-49
Development III in Microsoft Dynamics® AX 2012
3-50