Question

I've read about Autofac that it's fast. I've seen the coding involved and it's pretty neat. But I'm not quite sure how to use it. I've used StructureMap, and it has a static ObjectFactory. Ninject has the Kernel, but in Autofac's Google pages they recommend doing something like this :

using( var resolver = builder.Build() ){
   var whatINeed = resolver.Resolve<INeedThisService>();
}

It's a WinForms app, so I got an Invalid Object state from doing the above, so I switched to having a global IContainer, and did it this way

 using( var resolver = Program.Container.CreateInnerContainer() )
 {
     var whatINeed = resolver.Resolve<INeedThisService>();
 }

I've used it about 3 or 5 times. But is that efficient? Or should I just do something like

 var whatINeed = Program.Resolve<INeedThisService>()

and under the covers

 internal static TServervice Resolver<TService>(){
       if(_container == null ) _container = builder.Build();
       return _container.Resolve<TService>();
 }

Which would you use, and why? Also is there a penalty for working with CreateInnerContainer()?

Was it helpful?

Solution

I am not an AutoFac expert but do have experience with other Ioc containers. I thought this question would give me a reason to try AutoFac.

Designs based on Ioc containers should strive to isolate all code from having access to the container except at the entry point or host level. I created the following example using AutoFac and WinForms to show how a form could access a service via it's constructor.

I'm not quite sure why you thought you needed the inner container. Perhaps you could comment and I can provide a more detailed response.

static class Program
{
    [STAThread]
    static void Main()
    {
        var builder = new ContainerBuilder();
        builder.Register<TheService>().As<INeedThisService>();
        builder.Register(f => new Form1(f.Resolve<INeedThisService>())).As<Form1>();

        using (var container = builder.Build())
        {
            Application.Run(container.Resolve<Form1>());
        }

    }
}

public interface INeedThisService { }

public class TheService : INeedThisService
{
    public TheService() { Console.WriteLine("ctor ThisService"); }
}

public partial class Form1 : Form
{
    public Form1(INeedThisService service)
    {
        Console.WriteLine("ctor Form1");
        InitializeComponent();
    }
}

OTHER TIPS

1) From the examples you gave I could make an assumption that you are trying to use IOC container primarily as service locator. Although almost all containers support it, main usage would be Dependency Injection. That means you should avoid calling Resolve method at all and let container inject all dependencies for you. The differences between two of them (Service Locator and Dependency Injection) is beyond this topic.

2) If you still want to use it as service locator you can just use root container (Program.Container in your case) without creating inner containers. The sequence would be:

  • Create ContainerBuilder
  • Register you components in the builder
  • Create root container: builder.Build()
  • Access root container to resolve component instances

3) Container hierarchies can be useful in the scenarios where you need singleton behaviour in different scopes:

  • Global \ Session \ Request (Web applications)
  • Application \ Plugin (Desktop plugin-based applications)

BTW Autofac encourage people to use tagged contexts to solve such problems:

As Mark Lindell pointed out, you don't generally need to access the container directly in an Autofac application.

The recommended approach is to access it once, as Mark has done, when the application starts up.

Other components that subsequently need to create objects can declare a constructor parameter of type IContext, which Autofac will automatically inject.

An alternative, that does not require any dependency on the Autofac assembly, is to use Generated Factories as described at: http://code.google.com/p/autofac/wiki/DelegateFactories

Hope this helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top