berkeleybross
berkeleybross

Reputation: 1386

Resolving InstancePerHttpRequest inside "Singleton"

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

Answers (2)

Edwin Sukirno
Edwin Sukirno

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.

  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

Upvotes: 0

Rudis
Rudis

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

Related Questions