2

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?

berkeleybross
  • 1,314
  • 2
  • 13
  • 27
  • 2
    A singleton cannot contain a transient. The container will not differ from the configured life cycle based on one consumer, as a dependency can have multiple consumers. If a dependency is to be used by a singleton, it should itself be configured as a singleton . A transient can of course use the singleton dependency as well. – David Oct 01 '13 at 17:53

2 Answers2

0

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.

Rudis
  • 1,177
  • 15
  • 30
0

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.

  1. Convert Foo to accept Func
public class Foo {
    private readonly Func _barFunc;

    public Foo(Func barFunc) {
        _barFunc = barFunc;
    }
}
  1. Use DependencyResolver.Current object to resolve Func
builder.Register(c => new Foo(() => DependencyResolver.Current.GetService()))
   .As()
   .SingleInstance();

For more tips on Autofac scope, check out this link Autofac per request scope