Loading ...

Dependency Injection in Acumatica, and How It Differs from Helper Classes

As Acumatica customizations grow, the way shared logic is structured becomes increasingly important. Small projects often start with helper classes, but as business rules expand, integrations appear, and multiple screens need the same behavior, helper-based designs begin to show their limits. This is where Dependency Injection becomes not just useful, but necessary.

In Acumatica, Dependency Injection is supported through Autofac and integrates directly with graphs and graph extensions using the InjectDependency attribute. Understanding when to use Dependency Injection and when a helper class is still the right tool is key to building maintainable and production-ready solutions.

 

Helper Classes and Their Limitations

Helper classes are typically static or directly instantiated classes that expose reusable methods. They work well for pure logic that has no dependencies and no state.

A typical helper class might perform formatting, calculations, or simple transformations.

 

public static class AmountFormatter

{

    public static string FormatCurrency(decimal value)

    {

        return value.ToString("C2");

    }

}

 

This type of helper is safe, predictable, and easy to reuse. Problems begin when helpers are used for logic that depends on configuration, the database, external systems, or Acumatica context.

Over time, such helpers start to accept many parameters, rely on PXGraph being passed in, and mix responsibilities like configuration lookup, business rules, logging, and external calls. At that point, the helper becomes a hidden dependency container with no clear contract and no easy way to change behavior safely.

 

What Dependency Injection Solves in Acumatica

 

Dependency Injection forces explicit design. Instead of hiding dependencies, services declare them. Instead of instantiating classes inside graphs, Acumatica creates and injects them at runtime.

In Acumatica, DI is particularly valuable when logic:

  • Depends on setup tables or configuration
  • Needs to be reused across multiple graphs or extensions
  • Integrates with external systems
  • Needs logging, error handling, or environment-specific behavior
  • Should remain testable and replaceable

DI encourages smaller graphs, clearer responsibilities, and safer evolution of code.

 

A Real World Scenario

Consider a requirement where multiple screens need to send email notifications based on business events. These notifications must use Acumatica notification templates, be linked to documents, respect configuration, and log failures.

This logic clearly has dependencies and should not live in a helper class.

 

Designing the Service Contract

The first step is to define a clear interface that represents the behavior you want, not the implementation details.

This interface is explicit, reusable, and independent of any graph or screen.

 

Implementing a Service

The implementation uses Acumatica’s notification template infrastructure through TemplateNotificationGenerator. The service validates inputs, resolves templates, links activities to documents, and logs failures.

Injecting the Service into a Graph Extension

In Acumatica, services are injected using the InjectDependency attribute. You do not resolve services manually and you do not use service locators.

The extension remains thin and readable. It does not know how notifications are sent, only that they are.

 

Dependency Injection Versus Helper Classes

Helper classes are best when logic is pure, stateless, and dependency-free. Examples include formatting, calculations, mapping, and simple validations.

Dependency Injection is best when logic depends on configuration, infrastructure, external systems, or must be reused across many screens in a consistent way.

A good rule of thumb is simple. If the code could run without a graph and without configuration, it is probably a helper. If it needs setup, logging, external access, or multiple collaborators, it should be a service resolved through DI.

 

When Dependency Injection Is the Right Choice in Acumatica

Dependency Injection is especially valuable when building integrations, shared workflows, notification systems, background processing, or cross-module business logic. It shines in Graph Extensions, where inheritance is not available, and clean composition is required.

Autofac-based DI allows Acumatica customizations to scale without becoming tightly coupled or fragile.