How to get container for Autofac for WebAPI2?
Asked Answered
L

2

8

In Ninject I can get object needed for interface by using class WebContainerManager

Ninject definition:

 var logManager = new LogManagerAdapter(); 
 container.Bind<ILogManager>().ToConstant(logManager); 

Ninject usage:

var log = WebContainerManager.Get<ILogManager>().GetLog(typeof(WebApiApplication));

My question is how to do the same in Autofac, to get needed class for interface?

UPDATE 1: Im using WebAPi 2, not MVC.

Longlegged answered 14/7, 2015 at 11:0 Comment(2)
FWIW, this is the Service Locator anti-pattern, and is not generally a good idea. you should be using constructor or property injection instead.Whiting
Probably, I just wanted to do something quickly ... and was not able to find quick solution:). Thanks for comment.Longlegged
P
10

If you need access to Autofac container from the class that was resolved by Autofac itself, then you can specify dependency on IComponentContext that is automatically provided by Autofac.

Example:

public void SomeComponent(IComponentContext context)
{
   this.context = context;
}
...
// somewhere inside SomeComponent
context.Resolve<ILogManager>();

If your code is running inside ASP.Net environment, then you most probably set its DependencyResolver, thus you can always access it like:

DependencyResolver.Current.GetService<ILogManager>();

but as it is already mentioned in other comments, Service Locator is an anti-pattern that should be avoided.

In order to integrate autofac container with standard MVC dependency resolution mechanism you need to:

  • install Autofac.Mvc5 nuget package
  • set DependencyResolver with the following code

    var container = builder.Build(); DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

And in case you don't mind having explicit dependency on Autofac in your application code you can access global Autofac resolver reference the same way you use Ninject WebContainerManager:

var log = AutofacDependencyResolver.Current.Resolve<ILogManager>().GetLog(typeof(WebApiApplication));
Phinney answered 19/7, 2015 at 18:28 Comment(10)
DI is not the solution which I need in my question.Longlegged
Line: var x = (ILogManager)MVC.DependencyResolver.Current.GetService(typeof(ILogManager)); gives null :). Like this is not seeing my autofac container but it works:)Longlegged
I assumed that you already have DependencyResolution integration with Autofac in place. I updated answer with details on how to do that.Phinney
@Longlegged I have updated my answer to show how to access global Autofac container reference, just the same way you use Ninject WebContainerManager (although I do not advise to use it that way, but that was your question).Phinney
AutofacDependencyResolver is unknown (I have autofac 2 libs attached and autofaq forking instance). No option to add any namespace. Anyway I solved the problem by injection via contructor:), but I still curious how to do it:). Thanks for your efforts.Longlegged
@Longlegged AutofacDependencyResolver comes with Autofac.Mvc5 nuget package. So, you solved it by injecting IComponentContext to your component as I showed in first example of my answer?Phinney
Thanks. I using Web API 2:) .... I know that probably I can add this package:) but any specific solution for Web API2:)?Longlegged
For WebApi you need Autofac.WebApi nuget package and set HttpConfiguration.DependencyResolver in similar way. But you should have probably already set it?Phinney
My DI container works:), I just want to get this container in code:). HttpConfiguration has no such method like DependencyResolver.Longlegged
Let us continue this discussion in chat.Phinney
C
7

You can create your builder.

var builder = new ContainerBuilder();

// Usually you're only interested in exposing the type
// via its interface:
builder.RegisterType<SomeType>().As<IService>();

// However, if you want BOTH services (not as common)
// you can say so:
builder.RegisterType<SomeType>().AsSelf().As<IService>();

Then you will be able to build your IoC:

IContainer Container = builder.Build();

And a simple example of How to get resource from container:

// Create the scope, resolve your IService,
// use it, then dispose of the scope.
using (var scope = Container.BeginLifetimeScope())
{
  var writer = scope.Resolve<IService>();
  writer.DoSomething();
}
Corkwood answered 14/7, 2015 at 11:6 Comment(5)
Beautiful example and "How to start": docs.autofac.org/en/latest/getting-startedCorkwood
Still I have a problem with this, your Container is based on configuration via builder object. But I need the way to use it with existing configuration, in any part of code. Independly from configuration ... like my Ninject usage code...:)Longlegged
@Longlegged Could you please post here an example of your configuration ? Then I will try to clarify and will help you. ;) You can edit your main topic with your Autofac example/object registration.Corkwood
In you code I changed using (var scope = Container.BeginLifetimeScope()) into using (var scope = GlobalConfiguration.Configuration.DependencyResolver.GetRequestLifetimeScope()) to get container in code, and it works. Hopefully it ok:)Longlegged
My problem was that I have Autofac configured... and suddenly in code I want to get class for interface defined in Autofac. In you exmaple you are using builder because you have acess to it. In my scenario, I had no access to builder, so I needed the way to get Container. Is it more clear?Longlegged

© 2022 - 2024 — McMap. All rights reserved.