Using Autofac to inject a dependency into the Main entry point in a console app

autofac, c#

Solution

What you should do is extract all logic from your main into a class. This class can have a constructor with dependencies. You resolve this class in the main and call it. This class should then be considered to be the entire application. Everything that happens inside the `Program` class can now be considered your Composition Root.

// ** Begin composition root
public static class Program
{
    public static void Main(string[] args) 
    {
        var container = ConfigureContainer();
        var application = container.Resolve<ApplicationLogic>();

        application.Run(args); // Pass runtime data to application here
    }

    private static IContainer ConfigureContainer()
    {
        var builder = new ContainerBuilder();
        
        builder.RegisterType<ApplicationLogic>.AsSelf();
        builder.RegisterType<Log>().As<ILog>();
        // Register all dependencies (and dependencies of those dependencies, etc)

        return builder.Build();
    }
}
// ** End composition root

public class ApplicationLogic
{
    private readonly ILog log;

    public ApplicationLogic(ILog log) => this.log = log;

    public void Run(string[] args) => this.log.Write("Hello, world!");
}

Note that `container.Resolve<ApplicationLogic>()` doesn't just resolve the `ApplicationLogic` class, it resolves the entire object graph including all of `ApplicationLogic`'s dependencies, and dependencies of those dependencies, etc. no matter how deep the graph is. The only thing you are responsible for is registering those dependencies in the `ConfigureContainer()` method. Therefore, it is somewhat unusual to have any more than 1 `Resolve()` method call a console application, and if there are, they should always be called or wired up inside the Composition Root.

Problem

Say I have a simple console application: ``` public static class Program { private static ILog Log { get; set; } public static void Main() { Log.Write("Hello, world!"); } } ``` What is the simplest way I can use Autofac to inject the Log instance and ensure that the Log property will not be null at run time? The issue is that I can't pass it in through Main() and I'm trying to avoid service location using the container (just because).

Original source