AL DEVELOPMENT • DESIGN PATTERNS

Dependency Injection in Business Central AL: Practical Guide

Learn how to apply dependency-injection principles in Microsoft Dynamics 365 Business Central AL using interfaces, replaceable implementations and factory-style selection.

Dynexal · Business Central AL Development · Tutorial #17

What is dependency injection?

Dependency injection (DI) is a design technique where a component receives the behavior it depends on instead of creating or hard-coding that dependency itself.

Simple idea: The business process says what behavior it needs; another component supplies the implementation.

Why use DI in Business Central AL?

Interfaces are the foundation

AL interfaces provide a natural contract between a consumer and an implementation.

interface "Notification Provider"
{
    procedure SendMessage(Message: Text): Boolean;
}

Implement the contract

codeunit 50140 "Email Notification Provider" implements "Notification Provider"
{
    procedure SendMessage(Message: Text): Boolean
    begin
        // Email implementation
        exit(true);
    end;
}

Inject the dependency

A procedure can receive the interface as a parameter. The consumer does not need to know which concrete provider is being used.

procedure NotifyCustomer(
    Provider: Interface "Notification Provider";
    Message: Text): Boolean
begin
    exit(Provider.SendMessage(Message));
end;

Enum + interface pattern

An enum can represent the business choice while the interface represents the behavior.

enum 50140 "Notification Method"
{
    Extensible = true;

    value(0; Email) { }
    value(1; SMS) { }
}

A factory-style codeunit can map the selected enum value to the appropriate implementation. This keeps provider-selection logic in one place.

Dependency injection for integrations

DI is useful when Business Central connects to multiple CRM, e-commerce, shipping or middleware providers. Define a common contract and keep each provider's HTTP, authentication, JSON and mapping logic inside its implementation.

interface "Customer Sync Provider"
{
    procedure SyncCustomer(CustomerNo: Code[20]): Boolean;
}

Example architecture

Business Process
       |
       v
Interface Contract
       |
   +---+---+
   |   |   |
Provider A  Provider B  Test Provider

The business process depends on the contract. Implementations can change independently as long as they satisfy that contract.

DI and automated testing

A production implementation may call an external service, while a test implementation can return predictable results without making a real HTTP request.

codeunit 50142 "Test Notification Provider"
    implements "Notification Provider"
{
    procedure SendMessage(Message: Text): Boolean
    begin
        exit(true);
    end;
}

DI vs direct codeunit dependency

Direct dependencyInterface-based dependency
Consumer knows the implementationConsumer knows the contract
Replacement can require code changesImplementations can be replaced more easily
Testing may depend on concrete servicesA test implementation can be supplied

Common mistakes

Best practices

Real-world use cases

Frequently asked questions

Does AL support dependency injection?

AL supports the principles through interfaces, parameters and replaceable implementations. A separate general-purpose DI container is not required for these patterns.

Is DI useful for Business Central integrations?

Yes. It can separate provider-specific details from core business logic and make implementations easier to replace or test.

Should every codeunit use an interface?

No. Use abstraction where multiple implementations, replaceability, testability or reduced coupling provides a clear benefit.

Summary

Dependency injection is about controlling dependencies and keeping business logic flexible. In Business Central AL, interfaces provide a practical foundation: define a contract, implement it in one or more codeunits, and pass the required implementation into the business process.