Lucas Casagrande
Lucas Casagrande

Reputation: 508

Difference between creating a scope using Autofac LifeTimeScope and Asp.net Core DI Extension IServiceScopeFactory

I'm developing an application in Asp.net Core using the Autofac as the default DI and in my integration tests I require some services which before installing the Autofac I was injecting by creating a IServiceScopeFactory and then calling the method CreateScope() to be able to get the services needed, just like the code below:

public void ExampleOfAspNetServiceScope(){    
     var scopeFactory = _testServer.Host.Services.GetRequiredService<IServiceScopeFactory>();

     using (var scope = scopeFactory.CreateScope()){
         var service = scope.ServiceProvider.GetService<ISomeService>();
         // Some stuff...
     }
}

After installing the Autofac into my application I've found in the documentation the interface ILifeTimeScope and now my code could be rewriten as follows:

public void ExampleOfAutofacScope(){    
     var lifetimeScope = _testServer.Host.Services.GetRequiredService<ILifetimeScope>();

     using (var scope = lifetimeScope.BeginLifetimeScope()){
         var service = scope.Resolve<ISomeService>();
         // Some stuff...
     }
}

I did integration tests with both and it seems they behave equally. So, I was wondering what are the differences between the two approaches.

Thanks in advance.

Upvotes: 8

Views: 5451

Answers (2)

Yepeekai
Yepeekai

Reputation: 2723

It is mostly the same thing... as long as you don't override registrations in child scopes. IServiceProvider.CreateScope will create a new scope from the root one whereever the current IServiceProvider is. ILifetimeScope.BeginLifetimeScope will create a child scope of the current one. Here is the code to illustrate that (.Net 6 and Autofac 6.4):

var root = ((LifetimeScope)lifetimeScope).RootLifetimeScope;

using var ls1 = root.BeginLifetimeScope();
using var ls2 = ls1.BeginLifetimeScope();

var spRoot = root.Resolve<IServiceProvider>();
using var sp1 = spRoot.CreateScope();
using var sp2 = sp1.ServiceProvider.CreateScope();

bool isLs1ChildOfRoot = ((LifetimeScope)ls1).ParentLifetimeScope == root; //true
bool isSp1ChildOfRoot = ((LifetimeScope)((AutofacServiceProvider)sp1.ServiceProvider)
    .LifetimeScope).ParentLifetimeScope == root; //true

bool isLs2ChildOfRoot = ((LifetimeScope)ls2).ParentLifetimeScope == root; //false
bool isLs2ChildOfLs1 = ((LifetimeScope)ls2).ParentLifetimeScope == ls1; //true
bool isSp2ChildOfRoot = ((LifetimeScope)((AutofacServiceProvider)sp2.ServiceProvider)
    .LifetimeScope).ParentLifetimeScope == root; //true

bool sp1EqualsSp2 = sp1 == sp2; //false

For the most part, both will act the same way since scoped registrations will honnor the new scope and create a new instance in the child scope of another child scope. Problems arise when you use advanced features of autofac like overriding registrations or adding registrations in a child scope: If you create a new scope with IServiceProvider, you will lose those registrations because the new scope will be a child of root instead of the scope with the custom registrations.

Upvotes: 1

Travis Illig
Travis Illig

Reputation: 23924

It's the same thing, just using the Microsoft.Extensions.DependencyInjection abstractions instead of using Autofac directly.

I'd recommend looking at the actual code in Autofac.Extensions.DependencyInjection for more concrete clarity. There's not actually much to it and you can see for yourself precisely how it works.

Upvotes: 9

Related Questions