Example Extension: Interfaces in AL
One of the most impactful new features of the upcoming Business Central Spring Release 2020 will be interfaces. Interfaces are the strict building plan for implementing codeunits referencing on it. The interface itself only keeps the definition of the used methods, not the implementation itself.
Contract
Here’s our contract for the upcoming implementations of the interface including the method MyProcedure().
As you can see, we don’t find any code inside the procedure, but the exact definition of parameters and response.
interface "My Interface"
{
procedure MyProcedure(TextIn: Text): Text;
}
Implementation
Every codeunit implementing this contract must also exactly implement all methods defined in the interface. This might be two example codeunits:
codeunit 50100 "My Implementation 1" implements "My Interface"
{
procedure MyProcedure(TextIn: Text): Text
begin
exit(StrSubstNo('Hi, i am codeunit 1: %1', TextIn));
end;
}
codeunit 50101 "My Implementation 2" implements "My Interface"
{
procedure MyProcedure(TextIn: Text): Text
begin
exit(StrSubstNo('Hi, i am codeunit 2 and i am way better: %1', TextIn));
end;
}
Now i create a little setup record where we can choose the implementation we would like to work with. This ist just for testing purpose… you might think of an automatic factory or something:
table 50100 "Interface Setup"
{
DataClassification = ToBeClassified;
fields
{
field(1; Code; Code[10])
{
DataClassification = ToBeClassified;
}
field(5; "Used Interface"; Enum "My Interface Enumeration")
{
DataClassification = ToBeClassified;
}
}
keys
{
key(PK; Code)
{
Clustered = true;
}
}
}
As you can see, we can now hold enumerations in tables. We use this enumeration to store and choose our different implementations of the interface. If you make this enumeration extensible, other developers might also extend this and write their own implementation using the interface:
enum 50100 "My Interface Enumeration" implements "My Interface"
{
Extensible = true;
//Our standard or fallback implementation
value(0; "Undefined")
{
Implementation = "My Interface" = "My Implementation 1";
}
//Here's the different implementations
value(1; "Implementation 1")
{
Implementation = "My Interface" = "My Implementation 1";
}
value(2; "Implementation 2")
{
Implementation = "My Interface" = "My Implementation 2";
}
}
If we start the page, we can choose from our implementations:
So whats’s our status now? We have created a contract with the definition for the method MyProcedure() and two different implementations. In the little setup we could choose the specific implementation using an extensible enum.
But what to do with all this magic now?
Now we can “instanciate” the interface instead of the specific codeunits and use the methods completely equivalent. Aditionally, we could extend it without changing a single line of code in the standard application. So, basically, we’re only working with the interface and its methods, not the codeunits implementing it.
codeunit 50102 "Interface Test"
{
var
MyInterface: Interface "My Interface";
InterfaceSetup: Record "Interface Setup";
trigger OnRun()
begin
InterfaceSetup.Get();
//We get our implementation from the setup
MyInterface := InterfaceSetup."Used Interface";
//And call the method
Message(MyInterface.MyProcedure('Test'));
end;
}
The result is depending on our chosen implementation in the setup:
Here you can find the example AL project to download.
The requirement, for sure, is a docker container with the next major version (spring release 2020) from bcinsider program.