Dynamics 365 for operations extension patterns Prepared for Microsoft Internal
Table of Contents What is intrusive customization: .................................................................................................................. 4 Table Extension ............................................................................................................................................. 4 What is in scope: ....................................................................................................................................... 4 What is not in scope: ................................................................................................................................ 4 Best practice: ............................................................................................................................................ 4 Add a method to a table ........................................................................................................................... 4 Add a display or edit method to a table ................................................................................................... 5 Event handlers and delegates (hooks) ...................................................................................................... 7 Events listed inside the event node ...................................................................................................... 7 Pre and Post event handlers on public methods ................. .......................... ................... ................... .................. .................. .................. .................. ........... 8 Subscribe existing delegates on table methods................ methods......................... ................... ................... .................. .................. .................. .................. ............. .... 9 Class Extension ............................................................................................................................................ 10 What is in Scope: ..................................................................................................................................... 10 What is not in scope: .............................................................................................................................. 10 Best practice: .......................................................................................................................................... 10 Extension class declarations ................................................................................................................... 10 Reason why it is marked as final ......................................................................................................... 10 Methods in extension class ................................................................................................................. 11 Add new method to existing class .......................................................................................................... 11 Instance methods ................................................................................................................................ 11 Static methods .................................................................................................................................... 11 Add new state ......................................................................................................................................... 12 Instance state ...................................................................................................................................... 12 Static state .......................................................................................................................................... 12 Chain of Command ................................................................................................................................. 12 Wrapper methods must always call next............................................................................................ next............................................................................................ 12 The Hookable attribute ........................................................................................................................... 16 Final methods and the wrappable attribute .................. ........................... ................... ................... .................. .................. .................. .................. .............. ..... 16 Method signatures .................................................................................................................................. 16 Option 1: Method overloading ........................................................................................................... 17 Option 2: Class state ........................................................................................................................... 17 Option 3: Disposable context .............................................................................................................. 18
Register a subclass for factory methods ................... ............................ .................. ................... ................... .................. .................. .................. .................. .............. ..... 20 Respond by using EventHandlerResult or types that implement IEventHandlerResult ............ ..................... ............. .... 21 EventHandlerResult ............................................................................................................................ 21 Accept and reject request/response scenarios .................. ........................... .................. .................. .................. .................. ................... ................... ......... 21 Extend the RunBase class........................................................................................................................ 23 Limitations in class .................................................................................................................................. 27 Extension support for methods with DataMemberAttribute ............... ........................ .................. .................. .................. .................. ........... 27 Form Extension ........................................................................................................................................... 28 What is in scope: ................................................................................................................................. 28 What is not in scope: .......................................................................................................................... 28 Best practice: ...................................................................................................................................... 28 Form method .......................................................................................................................................... 29 Through chain of command ................................................................................................................ 29 Through pre-post event handlers ....................................................................................................... 29 Form Event .............................................................................................................................................. 31 Form Datasource method ....................................................................................................................... 32 Form Datasource field method ............................................................................................................... 33 Form Datasource Event ........................................................................................................................... 36 Form control Event ................................................................................................................................. 38 Enum extensions ......................................................................................................................................... 40 EDT extensions ............................................................................................................................................ 41 Report extensions: ...................................................................................................................................... 41 Frequently used patter in upgrade: ............................................................................................................ 43
What is intrusive customization: 1. 2. 3. 4. 5.
Don't change a method signature. Don't change requirements for implementers of interfaces and table maps. Don't change requirements for classes that are derived from abstract classes. Don't reduce access modifiers for types or members. Don't change constraints that are defined on a table or a data entity
Table Extension What is in scope: 1. 2. 3. 4. 5. 6. 7. 8. 9.
Adding new fields Field groups Indexes Mapping Relation Add new fields to existing field groups Change the label of a table field Change the Created By, Created Date Time, Modified By, Modified Date Time (except inherited table), country region codes properties etc. Adding new methods by COC
What is not in scope: 1. 2. 3. 4.
You cannot delete any element from standard table Unique indexes can't be changed Mandatory property Relation modification
Best practice: a)
Do not name the extension just .Extension. For example, an extension class that augments the custGroup table must not be named custGroup .Extension, because the risk of conflicts is too high.
b) Fields, indexes, relations, and other metadata elements on extension elements must have a name that is unique across both the element that is being extended and other extension elements. Therefore, these metadata nodes must include a term, abbreviation, or prefix that minimizes the risk of conflicts across models.
Add a method to a table In Dynamics 365 for operations, we won’t be able to add the new method or modify the existing method to the standard table or to an extension table. We can achieve this requirement by creating the extension class for the table. Example, a new field that is named MyInventLocationId was added to the InventTable table through extension. A data event handler was also created for the Inserting event, and you must implement the logic of filling the new field there. To encapsulate that action, you will create a new method on InventTable and name that method defaultMyInventLocationId.
You can now add new methods to the augmentation class. These methods will then appear in IntelliSense for variables of the InventTable type, just as if they were defined directly on the table. This behavior applies to both static methods and instance methods.
Add a display or edit method to a table The display and edit method modifiers are supported on table extensions. Requirement is to add a display method in the standard table, it can be achieved either by creating a table extension or static class .
Use of display method – form extension
To use this display method in the form \ Form list page – On form extension create a string control in the form design and set the following properties. Data source: SalesTable
Data Method: SASalesTableListPage_Extension::customerNameAlias Cache Data Method: Yes
Result – Name is been added as display method on form.
Event handlers and delegates (hooks) Note - We can write Chain of Command (Explained later in the document) for table methods like insert \ update \ delete, if they are already there in table else, we can use events on table. In PU17 we will have the ability to overwrite methods that are not implemented in the derived classes yet.
Events listed inside the event node Earlier AX versions, we could override the virtual methods of a table's base class to control the behavior that occurred during table operations, such as when creating, reading, updating, or deleting. In the current version, we instead use extensions to implement event handlers that are called from the base implementations of the table methods. There are already plenty of events (hooks) we can subscribe in AX and extend the existing functionality without overlayering or overriding the function we need to extend. You can find those under t he “Events” node of the application objects. Subscription is as easy as right clicking and selecting “Copy event handler method”, then you need to paste it into an eventHandlers class and write your own logic inside Example - subscribe to the ‘Deleted’ event of the table
Note - that the object methods (like insert, update, init, write.) we used to override in the AX 2012 now corresponds to two different events, as ‘Deleting’ and ‘Deleted’, and we no m ore call super() in our event handler methods. Execution of those compared to AX2012 works like below
On all events you subscribe you also hav e a parameter that contains an “event args” object for the corresponding event. However, this parameter is not always the event args class you exactly need. They are generally down casted to their most common base class (DataEventArgs for data related events or FormEventArgs for events on the form root) a nd you need to cast it back to the args class you need. Example
There are a lot of event handlers with down casted parameters like this one and it is impossible to list all of them here. Please refer below reference link – https://docs.microsoft.com/e .microsoft.com/en-us/dynamics3 n-us/dynamics365/unified-ope 65/unified-operations/dev rations/dev-Reference - https://docs itpro/extensibility/customiza itpro/extensib ility/customization-overlaye tion-overlayering-extensio ring-extensions#table-ext ns#table-extensions ensions
Pre and Post event handlers on public methods Beyond these events listed inside the Events node, there are Pre a nd Post event handlers which you can subscribe to existing public methods and run your own logic before or after the original method is executed. And it is possible to change the return type and access the method parameters using the XppPrePostArgs parameter like the example below
Note – Note – pre and post event handlers are not type safe. So, chain of command is recommended way for these methods.
Subscribe existing delegates on table methods There are already many delegate functions in table events section published by Microsoft.
Reference - https://docs.m https://docs.microsoft.com/en-us/ icrosoft.com/en-us/dynamics365/unified-operations/dev dynamics365/unified-operations/dev-itpro/extensibility/respond-event-handler-result
Class Extension What is in Scope: 1. 2. 3. 4. 5. 6. 7.
Public methods Protected methods Only methods that are defined in regular classes can be wra pped Static methods Instance state Static State Extension classes can wrap default parameters of method. However, the method signature in the wrapper method must not include the default value of the parameter.
What is not in scope: 1. Private methods only accessible by defining wrappable or hookable attribute as true. 2. Methods that are defined in extension classes cannot be wrapped by augmenting the extension classes. 3. Pre/Post eventhandler not supported for Protected method until hookable attribute is define as true.
Best practice: a) DO NOT name the extension of class simply as _MYExtension. _MYExtension. Element name should be append with _Extension. Example: MyClass_Extension or + _extension b) DO start the name of the extension class with the name of the type being augmented, and end it with the term _Extension.
Extension class declarations
Extension classes are classes that are adorned with the ExtensionOf attribute attribute and that also have a name that has the _Extension suffix. (This restriction on the naming might be removed later.) The name of the extension class is otherwise unimportant. The class augments the artifact that is specified in the ExtensionOf attribute, as shown in the following example.
Reason why it is marked as final Because the classes are instantiated by the r untime system, it's not meaningful to derive from the extension class.
The classStr compile-time function must be used and has two purposes:
It produces a compilation error if the MyClass class doesn't exist.
The compile-time function that is used tells the compiler what kind of artifact is augmented. Artifact names by themselves don't uniquely identify a given artifact to augment. For example, forms can have the same names as tables, classes, and enums. Any number of extension classes can augment a given artifact in a particular model. Extension classes are never referenced directly by the programmer, only by the runtime system.
Methods in extension class The public methods that are defined in extension classes provide additional functionality to the augmented class in the context of the model where the extension class is defined. Only public methods are exposed in this way. You can define private methods to help implement the public methods, but those private methods aren't part of the effective class. Because extension classes are final, methods can't be marked as protected.
Add new method to existing class Instance methods Suppose we want to add a new method ExtensionMethod to the SalesCopying class.
The following example shows how to call the method in the model.
Static methods Methods that are defined as public and static in the extension class are available as static methods on the artifact that is augmented.
The following example shows how to call the method in the model.
Add new state In addition to providing static and instance methods to an a rtifact, you can add instance state and static state.
Instance state Instance state, which is state that pertains to an instance of an artifact, can be specified on extension classes. The following example defines a state that is named state.
The following example shows how to use state in your code.
Static state Static state applies to the type instead of an instance of the type. The following example shows a static extension state. Static constructors are the parameter-less static methods that are named typenew. Static constructors can be defined on extension classes. It's guaranteed that the runtime system will call the constructor before the first reference to the extension type.
Chain of Command You can now wrap logic around methods that are defined in the base class that you're augmenting. You can extend the logic of public and protected methods without having to use event handlers. When you wrap a method, you can also access public and protected methods, and variables of the base class. it required use of the next keyword create a Chain of Command (CoC) for the method.
Wrapper methods must always call next Wrapper methods in an extension class must always call next, so that the next method in the chain and, finally, the original implementation is always called. This restriction helps guarantee that every method in the chain contributes to the result. In the current implementation of this restriction, the call to next must be in the first-level statements in the method body.
Here are some important rules:
Calls to next can't be done conditionally inside an if \ else statement.
Calls to next can't be done in while, do-while, or for loop statements.
A next statement can't be preceded by a return return statement. Because logical expressions are optimized, calls to next can't occur in logical expressions. At runtime, the execution of the complete expression isn't guaranteed.
Now we can add pre and post functionality to extensible methods in a much easier and readable manner than the previously used event handlers, also we are now able to access protected methods and variables directly in the extended class without problems. Now let’s check how it works with an example.
ExampleofCoC Create two classes, one is the base class of the other and add a method we want to extend called ‘testMe’. Add Infolog calls inside the method to track the execution
Create a new model, add reference for the class model we created above, and add an extension class for our child class.
The method we added here is the new chain of command definition. We use exactly the same notation as the original method we are extending and add a mandatory “next” keyword to the call which will wrap our extension code around the extended method. This next keyword separates the pre and post parts of our extension and mandatory to be called inside the chain of command method. When you call next(), it checks for other extensions in the queue and runs them in random order, lastly running the base code.
The advantage of chain of command is you can share the same method variables in the pre and post (before/after next() call) or share the same tts block inside your COC method.
ExampleofCoCwithreturnvalue COC also supports return value and parameter modification of the extended method in a much more readable manner. Extending a method with return value and parameters in COC is like below
Example
The Hookable attribute If a method is explicitly marked as [Hookable(false)], the method can't subscribe to pre-events and postevents by extenders. In the following example, anyMethod can't be subscribe to pre-events and post-events by extenders in a class that augments anyClass1.
Final methods and the wrappable attribute Public and protected methods that are marked as final can't be wrapped in extension classes. You can override this restriction by using the Wrappable attribute and setting the attribute parameter to tr ue ([Wrappable(true)]). Similarly, to override the default capability for (non-final) public or protected methods, you can mark those methods as non-wrappable ([Wrappable(false)]). ([Wrappable(false)]). In the following example, the doSomething method is explicitly marked as non-wrappable, even though it's a public method. The doSomethingElse method is explicitly marked as wrappable, even though it's a final method.
Method signatures Method signatures are not extensible – and will not be. Extensible parameters would be intrusive – in so many ways Breaks derived classes (signatures of overridden methods must match), Requires recompilation, No side-by-side support. A method's signature is the contract between caller and method. method. When new parameters are added, then callers can provide additional data that the method can act on. In isolation; a request for an extra parameter makes no sense. An extra parameter will not help anyone unless someone is passing it in, a nd someone is acting on it.
In the land of extensibility there are restrictions:
You cannot change the places a given method method is called, that would require overlayering. overlayering. But you can call the method from your own code (with control over the parameters). You cannot change the implementation of the method, that would require overlayering. But often you can add logic pre/post or wrap using Chain-of-command .
With these constraints, here are some options:
Option 1: Method overloading Scenario You need to pass extra information from your code to an existing method and act on it in a pre/post handler. Description X++ doesn't support overloading methods – but you can mimic the behavior by creating a new method (with new name) in an extension class. The extension method can take additional parameters and call the original method; with your logic before and after calling the original method. Example Here is an example of "overloading" the insert method on CustTable. Notice the first 3 parameters are identical to the parameters on the original insert() method.
Option 2: Class state Scenario You need to pass extra information from your code to a method on a class that is called via other method(s) on the class. Description X++ now supports adding class state via an extension. You can use this to store the extra information. Example Here is an example adding state and wrapping a method.
Here is an example using this. The standard implementation of initFromItemOrCategory() initFromItemOrCategory() calls initFromInventTable().
Option 3: Disposable context Scenario You need to pass extra information from your code to a pre/post handler somewhere downstream. Description It can be tempting to store the extra information in a global cache or variable. There is a better approach, which avoids stale data, and is type-safe. Create a singleton class for the context. The class must implement System.IDisposable, so it is disposed when it goes out of scope. The receiving code can access the singleton instance to extract the information. Example Here is an example of the context class:
Here is an example of the calling code:
Here is an example of the consuming code. The standard implementation of CustTable.Insert() calls DirPartyTable::createNew() – the example uses Chain-of-command to wrap the createNew method, and then accesses the context to get the information.
Caution Transferring state from one arbitrary place to another using a global variable (which the context class is) can lead to future logical errors – that can be very hard to detect and fix. Recommendation would be to limit the usage to situations where the scope and consequences are manageable.
Register a subclass for factory methods Reference https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/extensibility/registersubclass-factory-methods
Respond by using EventHandlerResult or types that implement IEventHandlerResult EventHandlerResult Delegate methods and delegate handler methods can be declared to support a request/response scenario, where the delegate calling logic requests the subscribers to provide a response. To support this scenario the EventHandlerResult class is most often passed as a parameter, and the delegate handler methods provide their result using one of the result methods on the class. However, the EventHandlerResult class can only contain a single result. The EventHandlerResult class has an a dditional static constructor which ensures that the logic fails if more than one subscriber provides a result. The new constructor is named newSingleResponse. When instantiating an EventHandlerResult object using this method, the framework will throw an exception as soon as a second delegate handler method attempts to provide a result.
The below example describe to provide a result from handler method.
Guidelines
In general, the logic that is implemented in the delegate handler method should contain a condition that verifies that the subscribing logic is responsible for providing a response. It s hould also include logic to provide the response in the form of a result. When the delegate handler method must provide the response to an EventHandlerResult object parameter, the subscribing logic might also contain logic to calculate or retrieve the result. When the condition and the response logic are implemented, the calculation of the result must occur only when the condition is evaluated to true. All the subscribing delegate handler methods are run when a delegate is called. Therefore, you should make sure that the overhead of running your method is as low as possible when the method isn't responsible for providing a response. Therefore, make sure that the condition is evaluated to false a s quickly as possible when your delegate handler method isn't responsible for providing a result.
Accept and reject request/response scenarios When using the EventHandlerAcceptResult class, the delegate handler method can only respond by calling the accept method.
Method
Delegate
Subscribermethod
When using the EventHandlerRejectResult class, only the reject method can be called. The following example shows a delegate handler method that responds by using an EventHandlerRejectResult object. To respond by using an EventHandlerRejectResult object, you can call the reject method or the checkFailed extension method. If you use the checkFailed method, you can add a warning message to the Infolog. Internally, the checkFailed method calls the reject method. Method
Delegate
Subscriber
Reference https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/extensibility/respondevent-handler-result
Extend the RunBase class How to extend the information shown on a R unBase-based dialog, and how to handle that information once the user enters the necessary data. Also, how to preserve the user entered data, so that next time the dialog is opened, it contains the last entries already populated. This is the typical pattern used across all AX forms and is internally based on the SysLastValue SysLastValue table. table.
Suppose we want to extend the SysUserLogCleanup class. Out-of-the-box this class is deleting records from the SysUserLog table. Let's imagine we want to archive these records to a different table before they are deleted. The SysUserLogCleanup class is a RunBase class. The RunBase class has a dialog box, where the user is prompted for parameters before the class is run. For this example, we will add a toggle button control to the dialog box, get the value of the control, act on the value in the run me thod, and make sure that the value is serialized via the pack and unpack methods. Serialization helps guarantee that the user’s last selection is presented again if the dialog box is reopened. It also helps guarantee that the settings are applied if the class is run in the background.
Reference https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/extensibility/extendrunbase-class https://blogs.msdn.microsoft.com/mfp/2017/01/31/extending-class-state/
Limitations in class Extension support for methods with DataMemberAttribute Dave Froslie - DataMemberAttribute support is a platform r equest that has been made by several sev eral partners. The request has some risk associated with it, and the best case is for it to be in PU19 which is several weeks out - https://msdyneng.visualstudio.com/FinOps/_workitems/edit/199219 https://msdyneng.visualstudio.com/FinOps/_workitems/edit/199219..
Form Extension What is in scope: 1. 2. 3. 4. 5. 6. 7. 8. 9.
Add a new control. Enable or disable a control. Change the text or label property of a control. Change a control's visibility. Change a form's help text. Change a form's caption. Add a new data source. Add a form part. Implement the code in class as COC a) Form methods b) Form data source method ( formdatasourcestr) c) Form data source field method ( formdatafieldstr) d) Form data source control methods (formcontrolstr)
What is not in scope: 1.
There is a limitation to handle the data source field control lookup.
Best practice: a) Do not name the extension just .Extension. or .Extension1… extended>.Extension1… For example, an extension class that augments the SalesParameters table must not be named SalesParameters.Extension, because the risk of conflicts is too high and also it would be carry the upgrade cost.
Form method Through chain of command We can use class extensions to author X++ logic associated with form extensions. This allows the definition of state variables accessible to form and control event handlers. It also allows overriding form methods without overlayering code. Example – Form name – BOMRouteCopyDialo B OMRouteCopyDialog g Customization: CloseOk():
Using chain of command –
Through pre-post event handlers Example – Retrieve the CustAccount when opening the InventNonConformance Form
Find the form that you want to extend in the AOT
Open the “Methods” node and copy an event handler for the init()method from here.
Form Event Extending form method example Now we have another option to extend the init method on the form. Option one is to open the “Events” node and hit “Copy event handler method” on the “OnIn itialized” event. OnInitialized is a post event, OnInitializing the opposite, a pre-event.
The difference is minimal, in both cases we will call args().record() from the FormRun object. When using the post handler on the init method, we will have to get this FormRun object first, not a big thing, we have just to call the getThis() method on the provided arguments of the handler. Result – Result – If we select a customer and hit “Non conformances” from the “SELL” tab on the CustTable form, we
will see the following Infolog.
Form Datasource method Now PU20 onwards, you can wrapped the form data source methods, data source field methods and control methods. Note - "What about our custom-made methods, we can’t add those to an extension class if they are under a datasource."
Answer - yes, you can add your custom methods (PU20) to DS on class extension. However, if there is any problem with methods implementation please moved the method to form level with some tricks. So, the pipeline is
Move your custom methods from DS level to Form level Move your custom form-level code to Extension class Create eventHandlers for required events Call your custom method using formhasmethod() Explained design below in Form Datasource field method
Form Datasource field method Common customization task to override standard form data source field methods like jumpRef(), modified() or validate(). Recommended approach in AX 7 is to avoid overlaying and use extensions as much as possible. To achieve this new event were introduced. However, on form data source field level we have only 3 available events:
For example, we want to add custom jumpRef() and validate() methods to itemId field on sales order form. First, we will create class to handle method overrides.
Then we will create new event handler class and subscribe to OnInitialized event of SalesLine data source.
Using this approach, you can override any data source field method. Note – “Known” issue - doesn’t work for lookup method on datasource field .
Form Datasource Event
Form control Event Below is the list of the Form > Design > control level event handler methods can be written - differs basing on the data type the control (For Combo box/enum type the event will be different). Example 1 –
Example 2 – Let say in our example we will write the event handler for the form data source > Design > Control level > Onlookup methods in the "LedgerJournalTransCu "LedgerJournalTransCustPaym" stPaym" standard form.
Open the Form > LedgerJournalTransCustPaym > Data Source (LedgerJournalTrans) > Design > Control level > Property_AgreementId is the custom field added to LedgerJournalTrans. Expand the Events (expand the events node). As shown in the above the screen shot. Right click on the Onlookup> copy the event handler method. Below is the screenshot.
Enum extensions You can extend any Enum that is marked extensible (IsExtensible=True) and
UseEnumValue = No
By extending an Enum, you can add new Enum values to it. It is important to k eep the following in mind when dealing with extensible Enums: 1. 2.
You cannot have X++ logic that depends on the integer value of Enum values (For example. If (Enum1.v1 > Enum1.v2) ... is not supported for extensible enums) When Enum values of extensible Enums are synchronized into the database:
Integer values that belong to the baseline enum are deterministic. They come from the metadata. Integer values that are an extension are generated during the synchronization process and are not deterministic.
Best practice: If your enum has many elements, such a s more than 100, consider redesigning the solution instead of making the enum extensible. If the enum is extensible, then adding more elements in the future might break customer’s combined solution as the addition might exceed the limit.
EDT extensions You can extend an EDT element in order to modify any of the following properties:
Form help Label String size Help text Note: For derived EDTs, string size can't be changed by an extension, because the IS-A relationship between
the EDTs will be broken. How to manipulate number of decimal if number of decimals extensible is false.
You can manipulate by parent EDT.
Report extensions: https://docs.microsoft.com/en-us/dynamics365/unified-operations/devitpro/analytics/custom-designs-business-docs
Note: For maintainability purpose, maximum print management report is getting call by getDefaultReportFormat instead of report name. Add a delegate handler method to start to use your custom report. Extend report. Extend the getDefaultReportFormatDelegate getDefaultReportFormatDelegate method method in your own custom class as below
Now you can extends the exiting controller class and use below code. Option 1:
Alternatively, you can implement wrapper class with below code. Option 2:
Note: if you faced an issue that the new report design was not being displayed even after Note: creating the above extension class (Option 1) and referring to the new report design, so you can resolved this issue by adding the below outputReport method: outputReport method:
Frequently used patter in upgrade: Pattern 1: Case structure Example:
How to adjust new cheque Type.
Pattern 2: error handling in extension code
Pattern 3: Initialize the table fields value Example:
Correct approach: Go to initializeSalesPackingS initializeSalesPackingSlipHeader() lipHeader() and initialize your fields after next call.
Pattern 4: How to write COC form data source methods.
Limitation: We cannot invoke one of these methods in a chain of command wrapper somewhere else because only the base code would be executed and COC code won’t be execute.
Example:
Pattern 5: How to cancel super call in from data source method before executing the standard validation.
Now you can call the COC for data source method and return true value.
Pattern 6:
Pattern 7: If method is predefine in table, you can write COC.
Pattern 8: form data source control level e vend hndler
However, jumpref is not displaying under events tree hierarchy, we can write event for jumpref as discussed in above.
Pattern 9: How to modify the data source field va lue in extension.
Pattern 10: how to access the members from data source methods.