6

I currently use Autofac to do simple constructor injection without any issues. However what I would like to know is how to resolve dependencies at runtime. The example below shows multiple ways in which we can export a document. With simple constructor injection the concrete implementation of IExport is resolved at runtime. However what need to do is to resolve IExport on a user selection from a dropdown list which will happen after the construction of my container. Is there any examples of how I can achieve this?

Public interface IExport
{
   void Run(string content);
}

public class PDFformat : IExport
{ 
   public void Run(string content)
   {
       // export in pdf format
   }
}

public class HTMLformat : IExport
{
   public void Run(string content)
   {
       // export in html format
   }
}

public class RTFformat : IExport
{  
   public void Run(string content)
   {
       // export in rtf format
   }
}

public class HomeController : Controller
{
   IExport Export;

   public HomeController(IExport export)
   {
      Export = export;
   }

   public void ExportDocument(string content)
   {
      Export.Run(content);
   }
}

Any help on this would be much appreciated.

Steven
  • 166,672
  • 24
  • 332
  • 435
Cragly
  • 3,554
  • 9
  • 45
  • 59

1 Answers1

8

You should use a factory:

public interface IExportFactory
{
    IExport CreateNewExport(string type);
}

Implementation:

class ExportFactory : IExportFactory
{
    private readonly IComponentContext container;

    public ExportFactory(IComponentContext container)
    {
        this.container = container;
    }

    public IExport CreateNewExport(string type)
    {
        switch (type)
        {
            case: "html":
                return this.container.Resolve<HTMLformat>();
            // etc
        }
    }
}

Registration:

builder.Register<IExportFactory>(
    c=> new ExportFactory(c.Resolve<IComponentContext>()))));
builder.RegisterType<HTMLformat>();
builder.RegisterType<PDFformat>();

Controller:

public class HomeController : Controller
{
   IExportFactory factory;

   public HomeController(IExportFactory factory)
   {
      this.factory = factory;
   }

   public void ExportDocument(string content)
   {
      this.factory.CreateNew("html").Run(content);
   }
}
Steven
  • 166,672
  • 24
  • 332
  • 435
  • Therefore would i pass in IExportFactory in my controller ? When I pass container in the registration as per builder.Register( container => new ExportFactory(container)); I get the following error cannot convert from 'Autofac.IComponentContext' to 'Autofac.IContainer' – Cragly May 23 '12 at 10:36
  • @Cragly: I'm sorry. I'm not a Autofac expert. You probably need to inject an `IComponentContext` (see my update). Yes, you'll need to inject an `IExportFactory` into your `HomeController`. – Steven May 23 '12 at 11:11
  • Thanks, got it working with following amendment to registration -> builder.Register( container => new ExportFactory(container.Resolve())); – Cragly May 23 '12 at 11:45
  • Please refer http://alexmg.com/selectively-resolving-services-at-runtime-with-autofac/ for a more concrete solution. – Nilesh Moradiya Aug 23 '16 at 07:11
  • I have used this thing in azure functions. Thanks a lot – Shrirang Feb 19 '20 at 08:48