Extending method signature using Disposable context
I am working on a project where we have majority of code ovelayered and we are trying to move on 8.1.X by removing over layering. The reason behind Overlayered code is upgrade , LCS upgrade service creates most of the code as overlayered and when upgrade happened in 2016 majority of objects were not extensible.
Its common practice to change method signatures in earlier version, here is nice article which shows different ways of achieving your goal without changing method signatures in dynamics 365 for finance and operations.
One of the option I used to achieve my goal is using disposable Context from the above link. Let’s take simple example of table CustGroup . Suppose you want to do something when customer group is deleted . We can do this using COC/event handler as well but just in case if you want it to be happen only in certain scenario. In AX 2012 it was very easy , just add parameter to delete method and whenever that parameter is true , do your action. Similar thing can be achieved using disposable context.
I created a simple runnable class ,context class and COC for delete method of CustGroup table .
Here is context class which I created. Advantage of using this is its gets dispose when it goes out of scope.
class MyCustGroupContext implements System.IDisposable { static MyCustGroupContext custGroupContext; public boolean deleteRecord; public void new() { if(custGroupContext) { throw error("Nesting is not supported"); } custGroupContext = this; } public void dispose() { custGroupContext = null; } static public MyCustGroupContext current() { return custGroupContext; } }
Then I created a COC for Custgroup delete method where I am using context class variable deleteRecord and check if it is set to true. If it is set to True , just giving info as customer group deleted.
[ExtensionOf(tablestr(CustGroup))] Final class MyCustGroup_extension { public void delete() { next delete(); MyCustGroupContext MyCustGroupContext = MyCustGroupContext::current(); if(MyCustGroupContext && MyCustGroupContext.deleteRecord) info("Customer group deleted"); } }
To test this , created a runnable class where just before calling delete method I am creating instance of the context class and setting deleteRecord variable to true.
class TestDisposableContext { public static void main(Args _args) { CustGroup custgroup; CustGroup = CustGroup::find('50' ); MyCustGroupContext MyCustGroupContext = new MyCustGroupContext(); MyCustGroupContext.deleteRecord = true; if (CustGroup) { ttsbegin; CustGroup.selectForUpdate(true); CustGroup.delete(); ttscommit; } } }
When I ran runnable class customer group 50 got deleted and I got the message which I wrote in COC of method.
Comments
-
Hello Sukrut, I think that the TestDisposableContext method is wrong, as MyCustGroupContext.dispose() method is never invoked. The correct version IMHO should be: class TestDisposableContext { public static void main(Args _args) { CustGroup custgroup; CustGroup = CustGroup::find('50' ); using (var MyCustGroupContext = new MyCustGroupContext()) { MyCustGroupContext.deleteRecord = true; if (CustGroup) { ttsbegin; CustGroup.selectForUpdate(true); CustGroup.delete(); ttscommit; } } } }
*This post is locked for comments