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()?
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();
}
}
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:
3) Container hierarchies can be useful in the scenarios where you need singleton behaviour in different scopes:
BTW Autofac encourage people to use tagged contexts to solve such problems:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With