Reputation: 1386
I'm trying to start using dependency injection inside an existing MVC4 app. I've installed Autofac 3.1.1 and Autofac MVC4 integration 3.1.0. I've been really pleased with it so far - however, I'm having difficulty with request scoping a disposable service:
namespace App_Start
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Autofac;
using Autofac.Integration.Mvc;
public static class KernelConfig
{
private static IContainer Container { get; set; }
public static void Register()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterType<Bar>()
.As<IBar>()
.InstancePerHttpRequest();
builder.RegisterType<Foo>()
.As<Foo>()
.SingleInstance();
Container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(Container));
}
class Foo
{
private readonly IBar _bar;
public Foo(IBar bar)
{
_bar = bar;
}
}
interface IBar
{
void DoStuff();
}
class Bar : IBar, IDisposable
{
public void DoStuff() { }
public void Dispose() { }
}
}
}
If I request an instance of IBar in a controllers constructor, everything works as expected - a new Bar is made every time and destroyed everytime. However, if I request a Foo in my controllers constructor I get the following message:
"No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested"
As far as I can work out, Autofac is creating a new Foo as a singleton. While this may seem obvious (I requested it to be a singleton) I would expect Autofac to walk the dependency tree and use the same lifetime across the entire tree. (I.e. if a singleton contains a transient, then both should be transient)
Is this the expected behaviour? What am I doing wrong?
Upvotes: 2
Views: 999
Reputation: 26
The exception is thrown because the code is trying to resolve an InstancePerHttpRequest object within a single instance object.
With some modifications you can achieve this.
public class Foo { private readonly Func _barFunc; public Foo(Func barFunc) { _barFunc = barFunc; } }
builder.Register(c => new Foo(() => DependencyResolver.Current.GetService())) .As() .SingleInstance();
For more tips on Autofac scope, check out this link Autofac per request scope
Upvotes: 0
Reputation: 1217
You can use dependency to IBarFactory instead of IBar. IBarFactory will have sigleton lifestyle and it will return IBar instance, which will be resolved from container.
Upvotes: 0