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

时间:2019-04-23 15:05:48

标签: c# autofac ioc-container

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 ?

2 个答案:

答案 0 :(得分:1)

创建新的IOutput类型后,

首先,您需要使用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();

然后,在WriteDate()方法中,通过使用带有Ioutput参数的ResolveNamed方法来指定要使用的name类型,该参数是在注册时指定的名称。类型:

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();
  }
}

注意:如果您不使用string的名称,则可以使用Keyed来使用enumeration的名称。

答案 1 :(得分:0)

AutoFac通过依赖IEnumerable<T>直接支持此功能。看到IEnumerable时,它将返回满足接口T的所有已注册类型的集合。

在您的情况下,注册LogsOutput,并将ConsoleOutput注册为IOutput,并解析IEnumerable<IOutput>,以获取两个注册服务。


更多详细信息,请参见here

  

可枚举类型的依赖项提供了多种实现   相同的服务(接口)。这在诸如消息之类的情况下很有用   处理程序,其中有一条消息传入,并且有多个处理程序是   注册以处理该消息。