Hierarchy conflicts in AX 7 during migration from other AX versions and it's resolution - Delegates and Handlers
Delegates and Handlers in AX 7(Hierarchy conflicts resolution)
Hi,
We recently did a migration of our AX 2012 solution to AX 7, and while doing so one of the major challenge that we have faced are hierarchy conflicts. I'll be discussing here on the same.
First of all we need to know that what is a hierarchy conflict.
Coming to the AX 7 architecture, Application stack is divide into three basic packages. These are-
1: Application Platform
2: Application Foundation
3: Application Suite
As shown in the above image, Application platform is the base package which contains Runtime and data access , work flow and services etc. and on top of it we have application foundation which contains organisation model, number sequence and GAB etc. and at the top we have Application Suite and Fleet Management. To understand the concept of these packages in depth you can follow the below link-
All three models follows a hierarchy. Application platform will be having access to elements from it's own package. Elements from application platform can't refer to elements from packages on top of it. In the same way Application foundation can have access to it's own elements and elements from Application Platform, but not from Application Suite. Application suite can access elements from both lower models and it's own elements.
Hierarchy Conflict:
Now the question comes what is a hierarchy conflict. So lets consider a scenario where an element which lies in Application Foundation is trying to use properties of an objects which is from application suite.This is an example of hierarchy conflict because Application foundation can access it's own objects and elements which belongs to model below i.e. Application Platform. It can't access elements of higher models.
Let's understand it with a simple example:
Lets consider two classes "SalesPrice" and "Profit".
1: SalesPrices (Application Foundation)
2: Discount (Application Suite)
public class SalesPriceClass
{
real cost;
real profit;
public real calculateSalesPrice()
{
real salesPrice;
salesPrice = this.cost + this.profit;
return salesPrice;
}
}
This SalesPrice is not the actual salesPrice. Consider a discount scenario which needs to be deducted form the current salesPrice to get the actual salePrice. And this discount belongs to a different class.
Other class is "Discount"class which belongs to Application suite;
public class Discount
{
static real discountValue;
}
Now it's not possible in the SalesPriceClass to get the discountValue and get the actual salesPrice by subtracting from the salesPrice beacuse SalesPriceClass (ApplicationFoundation) can't access the elements of Discount (Application Suite).
Now how to resolve such a scenario (hierarchy conflict).
The best method to resolve such a conflict is to use a Delegate.
How to use Delegates and Handlers
A delegate declaration must have three things:
- The delegate keyword
- Type void
- Empty method
delegate void applyDiscount_delegate(real _cost, EventHandlerResult _res) {}
Adding the SubscribesTo keyword to a method will create a static delegate handler. SubscribesTo requires the class name of the delegate, and the string name of the delegate method.
[SubscribeTo(classStr(SalesPriceClass), delegateStr(SalesPriceClass, applyDiscount_Delegate))]
public static void onApplyDiscount_Delegate(real _cost, EventHandlerResult _res)
{
real actualCost = _cost - discountValue;
_res.result(actualCost);
}
In order for a delegate to be properly handled, the delegate method declaration, the delegate instance, and the delegate handler must have the same method signature.
Due to the fact that delegates do not have a return value, an EventHandlerResult is passed as a parameter to provide access to the needed result value after the delegate has returned.
Our Example -
In our scenario, we will modify SalesPriceClass and add a new delegate to the class.
SalesPriceClass in ApplicationFoundation Model-
public class SalesPriceClass
{
real cost;
real profit;
//Adding a new delegate
delegate void applyDiscount_Delegate(real _cost, EventHandlerResult _res){}
public real calculateSalesPrice()
{
real salesPrice;
EventHandlerResult result = new EventHandlerResult();
//salesPrice = this.cost + this.profit;
this.applyDiscount_Delegate(cost, result);
salesPrice = result.result() + profit;
return salesPrice;
}
}
Discount Class in ApplicationSuite Model-
public class Discount
{
static real discountValue;
[SubscribeTo(classStr(SalesPriceClass), delegateStr(SalesPriceClass, applyDiscount_Delegate))]
public static void onApplyDiscount_Delegate(real _cost, EventHandlerResult _res)
{
real actualCost = _cost - discountValue;
_res.result(actualCost);
}
}
Important Note:
Concept of Delegates is only applicable to methods.
Find delegates and handlers
There are three key ways to find delegates and handlers- Metadata search
- Class references
- SubscribesTo references
In the search field, type “code:<delegate name>” which will restrict the search to code and find any use of the delegate name, returning both the delegate and handler. Metadata search will search the entire code base and may take some time to complete, but will return any use of the search term in code.
Methods two and three can be used in parallel to the metadata search. The class where a delegate is defined can also serve as a means to narrow down the search for a delegate or handler. The SubscribesTo keyword requires the class name where the delegate was defined. Visual Studio’s find references (right-click the class name > find references) will return a list of files that reference the class. This list will include both the class definition where the delegate is declared and the handler referencing the class. Finding class references is not a perfect method and will require some manual searching through class references. However, it produces a smaller subset of files and can be faster than a metadata search.
Comments
Post a Comment