Dependency Injection with Acumatica and Autofac from inside customization

Hello everybody,

today I want to write a few words about something that I consider as cool achievement: dependency injection in Acumatica with help of Autofac. Before sharing any code I'd like to mention why Autofac and not other framework? Because Acumatica itself is built on Autofac. For you as a developer it basically means that you can omit nuger versioning or any kind of versioning with Acumatica. You just reference Autofac, and it will be available for you in your project.

Keeping this idea in mind, let's suppose that you have following class in your code:

public class EmailNotificationSender : IEmailNotificationSender
{
    public void SendEmail(string to, string subject, string body)
    {
        var sender = new NotificationGenerator
        {
 
            To = to,
            Subject = subject,
            Body = body,
            BodyFormat = EmailFormatListAttribute.Text
        };
 
        sender.Send();
    }
}

This class implements following interface:

public interface IEmailNotificationSender
{
    void SendEmail(string to, string subject, string body);
}

And now question, how to inject this class? I propose to do it via creating extension for PXGraph.

Suppose you've created extension for PXGraph. If you make extension for PXGraph, let's name it GraphDI, then following will happen: Acumatica for each of your graphs will provide Graph Extension with name GraphDI. 

Coming back to our example I did the following:

  1. Created class GraphDI and in method Initialize registered all dependencies
  2. In places where my injection is really needed I've resolved dependency with help of Autofac

In order to be more detail oriented take a look at the following code. 

1. 

using Autofac;
public class GraphDI : PXGraphExtension<PXGraph>
{
    public IContainer Container { getset; }
    public override void Initialize()
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<EmailNotificationSender>().As<IEmailNotificationSender>();
 
        Container = builder.Build();
    }
}

As you can see, I've added reference to Autofac. Then I've registered interface IEmailNotificationSender with type EmailNotificationSender.

2. Resolving injection ( somewhere in the graph ):

var di = this.GetExtension<GraphDI>();
using (var scope = di.Container.BeginLifetimeScope())
{
    var snd = scope.Resolve<IEmailNotificationSender>();
    snd.SendEmail(SetupRecord.NotificationEmail, $"Sales order import errors for {DateTime.Now:d}", errorsSb.ToString());
}

as you can see from the sample, I've just got extension, and from extension got needed implementation of interface.

P.S. Unfortuantely attribute [InjectDependency] didn't work for me. I mean something like this gave me null:

[InjectDependency]
public IEmailNotificationSender EmailSender { getset; }

No Comments

Add a Comment