72

What are the differences between the two scopes?

I am building Module(s) in each layer (Repository, Service, MVC App), but in order to have InstancePerHttpRequest you need the Autofac.Mvc assembly.

Which scope should I be using in my Repository and Service layer?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Sam
  • 15,336
  • 25
  • 85
  • 148

3 Answers3

131

InstancePerHttpRequest and InstancePerApiRequest essentially do the same thing - you get a single instance of your service for each discrete web request. I'll use InstancePerHttpRequest for the rest of the answer, but keep in mind that these two are interchangeable.

InstancePerLifetimeScope means a new instance of the service will be created for every lifetime scope which asks for your service. Each web request gets its own fresh lifetime scope, so in practice, more often than not, these two will do the exact same thing.

The only real difference comes if you have a service registered under InstancePerHttpRequest and you request one of those services from another service which is registered as a SingleInstance. In this scenario:

  • The SingleInstance component lives in the root scope
  • The InstancePerHttpRequest component lives in a scope called "AutofacWebRequest", which is a child of the root scope

Autofac does not allow for resolution from child scopes - so essentially, the SingleInstance service cannot find the InstancePerHttpRequest service.

However, if in this scenario you had used InstancePerLifetimeScope (instead of InstancePerHttpRequest), then your services would resolve just fine.

I've written up a fairly exhaustive article with downloadable code that attempts to explain all this in detail - see here. Quoting from the article:

One common misconception here is that registering your component with InstancePerLifetimeScope in a WebAPI application means that your component lives in the scope of a web request – i.e. that “Lifetime” refers to “the Lifetime of the web request”. As you can see here, this is false.

The lifetime of your component is determined by the scope in which it was resolved.

Since the SingletonResolvable resolves its token from the root scope, that token instance lives in the root scope, not the scope of a web request. I’ve said it before, but I’ll say it again: this token will live until the entire application is disposed of (e.g. the IIS worker process is recycled). Anything which asks for a ScopeToken from the root scope will be given a reference to that token.

starball
  • 20,030
  • 7
  • 43
  • 238
gerrod
  • 6,119
  • 6
  • 33
  • 45
  • That article was extremely helpful. Great diagrams and demo app. Helped me immensely in figuring out the answer to my own question [here](http://stackoverflow.com/questions/36173210/get-same-instance-of-a-component-registered-with-autofac-as-instanceperlifetimes/36187071#36187071) – joelmdev Mar 23 '16 at 19:36
  • In case anyone is trying this in asp.net core, since it has its own DI, when using autofac you have to use `InstancePerLifetimeScope` instead of `InstancePerRequest`. More information [here](http://docs.autofac.org/en/latest/integration/aspnetcore.html#differences-from-asp-net-classic) – Rafael Merlin Oct 25 '17 at 02:19
  • In my case, I have a web project which has until now been using 'InstancePerRequest' for my Autofac configuration. Now, I want to reuse (most) of the same configuration to include in a separate Job runner application which accompanies my web application. Therefore, will I see the same functionality if I change all instances of 'InstancePerRequest' to 'InstancePerLifetimeScope()', yeah? Thanks – Ciaran Gallagher Dec 18 '17 at 15:13
  • 1
    @CiaranGallagher - that will probably work, but it won't be quite the same. We handle that scenario by creating our own named lifetime scope tag and then using `InstancePerMatchingLifetimeScope` which is effectively what `InstancePerRequest` does under the covers. Then, we start a new lifetime scope per job with our lifetime scope tag. Hope that helps! – gerrod Dec 18 '17 at 22:33
  • I'm not 100% how to do this, so I've opened a question here: https://stackoverflow.com/questions/47884141/autofac-scope-configuration-for-multi-project-solution Thanks – Ciaran Gallagher Dec 19 '17 at 09:49
7

The only place in your application that's completely capable of making a decision about the lifetime of an object is at the composition root.

In this case you have a conflict -- you have a generic module that shouldn't have access to extension method provided by the MVC integration -- yet you need to have access to it in order for the lifetime to be managed properly. In this case, if your module can provide a reasonable default, like InstancePerLifetimeScope, then that's what I'd do at the module level. Then, you let the composition root override that behavior. In this case the composition root would change the lifetime to InstancePerHttpRequest. Since the last registration will override the earlier registrations, you should be in good shape.

I've actually moved away from creating modules that coexist with the assembly that contains a given layer for a couple of reasons:

  1. It introduces a dependency on Autofac, which I don't want except at my composition root
  2. It suggests that the module knows how it's lifetime should be managed, which isn't usually true. If it does, why not provide a factory or other classes which provide that lifetime management?

Instead (and in projects large enough to warrant), I create the modules at the composition root level as at this level I have explicit knowledge about how they should be wired together. Sometimes I'll create an Ioc assembly that contains the modules and that acts as a default composition root -- but this is often overridden at the "real" composition root (e.g., the console or MVC application that pulls in the Ioc assembly).

Kaleb Pederson
  • 45,767
  • 19
  • 102
  • 147
  • 2
    You may not have any dependencies on Autofac except at the project root, however you're going to be highly dependent upon whatever IOC you might replace Autofac with behaving exactly like autofac. I think these kinds of implicit dependencies can be a whole lot harder to manager than explicit ones. – Mick Feb 16 '16 at 06:50
2

In Autofac per lifetime scope is a generic way to create custom scopes using nested lifetimes.

Using InstancePerLifetimeScope gives you per request scope, which adds component lifetime for single request and internally uses InstancePerLifetimeScrope for this component.

Use InstancePerLifetimeScope everywhere you need this, or if it is a problem to have a reference to Autofac.Integration.Mvc assembly in your service layer - create nested scopes manually on each beginning of request and use InstancePerLifetimeScope.

whyleee
  • 4,019
  • 1
  • 31
  • 33
  • Then I should be using `InstancePerLifetimeScope` in my service and repository modules and `InstancePerHttpRequest` in my global.asax? – Sam Aug 26 '12 at 01:40
  • 1
    Nope, if you're not creating nested scopes manually, per lifetime scope will be a singleton scope. So you better should use request scope everywhere or manually create nested scopes on beginning of each request. – whyleee Aug 26 '12 at 02:23
  • so I need to use InstancePerHttpRequest in my services and repository modules? Do you have an example of creating a scope that lasts only per request that I could implement? Thanks! – Sam Aug 26 '12 at 02:29
  • Yes. Other good suggestion, as Kaleb proposed in his answer, is to move all your Autofac modules to MVC project - then you will get rid of unnecessary Autofac dependencies and lifetime logic in several layers, that better should be in one place at the entry point of your application. – whyleee Aug 26 '12 at 12:32
  • 1
    To create nested lifetimes per request, use `BeginLifetimeScope` method on current lifetime (can be injected to your type as `ILifetimeScope` or got from `AutofacDependencyResolver.Current.RequestLifetimeScope`) on BeginRequest ASP.NET event. And dispose your nested lifetime in EndRequest event. – whyleee Aug 26 '12 at 12:38