Search code examples
c#autofacioc-container

How Autofac helps You to inject multiple instances of a class/interface in an existing class at the same time


I'm very new to Autofac and don't understand still all the potential. Let's take the example considered in the quick autofac tutorial in the website documentation. (https://autofac.readthedocs.io/en/latest/getting-started/index.html)

using System;

namespace DemoApp
{

 public interface IOutput
 {
   void Write(string content);
 }

 public class ConsoleOutput : IOutput
 {
    public void Write(string content)
    {
        Console.WriteLine(content);
    }
  }

  public interface IDateWriter
  {
     void WriteDate();
  }

  public class TodayWriter : IDateWriter
  {
     private IOutput _output;
     public TodayWriter(IOutput output)
     {
         this._output = output;
     }

     public void WriteDate()
     {
         this._output.Write(DateTime.Today.ToShortDateString());
     }
 }
}

And the Autofac glue looks like this:

using System;
using Autofac;

namespace DemoApp
{
   public class Program
   {
     private static IContainer Container { get; set; }

   static void Main(string[] args)
   {
       var builder = new ContainerBuilder();
       builder.RegisterType<ConsoleOutput>().As<IOutput>();
       builder.RegisterType<TodayWriter>().As<IDateWriter>();
       Container = builder.Build();

       WriteDate();
   }
  }
}


public static void WriteDate()
 {
  // Create the scope, resolve your IDateWriter,
  // use it, then dispose of the scope.
  using (var scope = Container.BeginLifetimeScope())
  {
    var writer = scope.Resolve<IDateWriter>();
    writer.WriteDate();
  }
}

The purpose of this program is simply to print the datetime on the console. Suppose now that I want to print the datetime not only in the console but also in the logs. For this purpose i want to create another class having interface IOutput like this:

public class LogsOutput : IOutput
{
    public void Write(string content)
    {
        // write content to a log file here
    }
 }

This is a pure example. I want to extend this example to a bigger problem. Now how should look like the Autofac glue code ? in order for the code to execute both ConsoleOutput classe and LogsOutput class and to print the output to both the console and the log file ?

Is it possible to achieve this with Autofac or is this not in the behaviour of autofac ? I possibly want to ba able to add hundreds of classes all with the IOutput interface. How to achieve this with Autofac ?


Solution

  • After creating a new IOutput type,

    First you need to register it in the container, using Named:

    var builder = new ContainerBuilder();
    builder.RegisterType<ConsoleOutput>().Named<IOutput>("console");
    builder.RegisterType<LogsOutput>().Named<IOutput>("logs");
    builder.RegisterType<TodayWriter>().As<IDateWriter>();
    Container = builder.Build();
    

    Then, in the WriteDate() method you specify type of Ioutput to use by calling ResolveNamed method with name parameter, which is the name specified in the registration of the type :

    public static void WriteDate()
     {
      // Create the scope, resolve your IDateWriter,
      // use it, then dispose of the scope.
      using (var scope = Container.BeginLifetimeScope())
      {
        var writer = scope.ResolveNamed<IDateWriter>("console"); // for console output
        //var writer = scope.ResolveNamed<IDateWriter>("logs"); // for logs output
        writer.WriteDate();
      }
    }
    

    NB : if you don't work with string names, you can use Keyed which work with enumerations .