AX 7. Breaking dependencies. Part 1.

Model dependencies is a new term in AX dev world. In previous versions we did not have to care about it because AX had one big namespace and you were able to call any x++ code without referencing it.

In AX 7 all the code is divided into models. Each model compiles into its own assembly (see AX wiki ).

Now if your class belongs to a model A and you want to use a code from a model B you have to add reference to it. AX 7 supports only one way references, so if the model A refers to the model B then the model B cannot refer to the model A. It is also known as circular dependencies.

This problem can be overcome by using interface and events.

Today we will talk about interface approach. To help us with this Microsoft created SysPluginFactory class.

Let’s look at the GeneralLedgerIExtension interface and its implementation as an example.


As you can see GeneralLedgerIExtension interface and GeneralJournalEntry table belongs to GeneralLedger model and GeneralLedgerExtension class belong to Application Suite. At the same time Application Suite has a reference to GeneralLedger thus GeneralJournalEntry table cannot use GeneralLedgerExtension directly.

To handle this SysPluginFactory class comes into play. We will walk through the code below line by line. It consists of three main parts:

1. Interface marked with [ExportInterfaceAttribute()] attribute.

using System.ComponentModel.Composition;

public interface GeneralLedgerIExtension

2. Class that implements interface. It is marked with [ExportMetadataAttribute()] and [ExportAttribute()] attributes. Where:

  •  ExportAttribute accepts interface name.
  •  ExportMetadataAttribute accepts key and value. Key should be the same for all implementations and value should be different.
using System.ComponentModel.Composition;

[ExportMetadataAttribute("GeneralLedger", "GeneralLedger"),ExportAttribute("Dynamics.AX.Application.GeneralLedgerIExtension")]
public class GeneralLedgerExtension implements GeneralLedgerIExtension

3. Code that instantiate the class:

//interface type variable
GeneralLedgerIExtension generalLedgerExtension = null;

//instance of SysPluginMetadataCollection that holds key-value pair.
SysPluginMetadataCollection metadataCollection = new SysPluginMetadataCollection();
metadataCollection.SetManagedValue("GeneralLedger", "GeneralLedger");

// instantiates the class using SysPluginFactory. It will find interface
// implementation marked with key-value specified in the metadataCollection.
generalLedgerExtension = SysPluginFactory::Instance("Dynamics.AX.Application", classStr(GeneralLedgerIExtension), metadataCollection);


We can notice that hardcoded string is used as a value in SetManagedValue() method to select interface implementation, however you can use enum or field value from a parameter table. Using parameter table may be useful in scenarios where a user will switch between implementation, for example choosing a price engine.
You can use this code as a starting point to create your own plugins.
Also SysPluginFactory can be used instead of construct pattern. Is has a couple of benefits:

  1.  Base class does not know about derived classes.
  2.  You don’t need to change code of base class to add new derived class.