Design patterns part 1 -PLUGIN
This is the first entry in the series of patterns related to Dynamics 365 Finance and Operations. Today we discuss about plugins.
Why we need plugins ?
Plugin allows the addition of features to an existing program. It is a creational pattern which allows to create types based on rules or navigate a hierarchy of types. The plugin resolution of types is done at run time and not at compile time. It can be used to replace the pattern below. If we want to add a new FooClass4 the below code and enum FooEnum needs to be modified.
public static FooClass construct(FooEnum _enumtype) { switch(_enumtype) { case FooEnum::Enum1: return new FooClass1(); case FooEnum::Enum2: return new FooClass2(); case FooEnum::Enum3: return new FooClass3(); default: return null; } }
The plugin can be used to create extensions to existing logic. It allows the addition of a new specialization or strategy.
Create a new Dynamics 365 for operations project and name it PluginTutorial. Add reference to Microsoft.Dynamics.AX.Platform.Extensibility.dll. The dll can be found in folder J:\AosService\PackagesLocalDirectory\Bin
Create an abstract class Engine which has the ExportInterfaceAttribute. Add static instance method to create the instances of the objects. The objects created are TruckEngine/CarEngine based on rules.
[Microsoft.Dynamics.AX.Platform.Extensibility.ExportInterfaceAttribute] public abstract class Engine { abstract void start() { } public static Engine instance(str _enginetype) { Engine engine=null; SysPluginMetadataCollection metadataCollection = new SysPluginMetadataCollection(); metadataCollection.setmanagedvalue(“EngineType”, _enginetype); return SysPluginFactory::Instance(“Dynamics.Ax.Application”,classstr(Engine),metadataCollection); } }
Create the TruckEngine and CarEngine types. Use the attributes ExportMetaDataAttribute and ExportAttribute
[System.ComponentModel.Composition.ExportMetadataAttribute('EngineType', 'Truck'), System.ComponentModel.Composition.ExportAttribute('Dynamics.AX.Application.TruckEngine')] Class TruckEngine extends Engine { void start() { Info(“Vrooooom(Truck engine started)”); } } [System.ComponentModel.Composition.ExportMetadataAttribute('EngineType', 'Car'), System.ComponentModel.Composition.ExportAttribute('Dynamics.AX.Application.CarEngine')] Class CarEngine extends Engine { void start() { Info(“Drooooom(Car engine started)”); } }
Now to you use the types we create a runnable class for testing
Class runnableclass1 { Public static void main(Args _args) { Engine.Instance(“Truck”).start(); //Truck started Engine.Instance(“Car”).start(); //Car started } }
Now the beauty of the pattern come if we want to add another extension by creating a BusEngine. None of the above Types Engine,TruckEngine or CarEngine need to be modified.
Create a new class BusEngine
[System.ComponentModel.Composition.ExportMetadataAttribute('EngineType', 'Bus'), System.ComponentModel.Composition.ExportAttribute('Dynamics.AX.Application.BusEngine')] Class BusEngine extends Engine { void start() { Info(“Gear change..boooom(Bus engine started)”); } }
Now we modify the runnable class to add the extension call
Class runnableclass1 { Public static void main(Args _args) { Engine.Instance(“Truck”).start(); //Truck started Engine.Instance(“Car”).start(); //Car started Engine.Instance(“Bus”).start(); //Bus started } }
*This post is locked for comments