question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cross-wired scoped services don't support nested scoping?

See original GitHub issue

I’ve encountered a situation in which cross-wired scoped service (e.g. DbContext) needs to be isolated in a nested scope via SimpleInjector’s nested scoping capabilities.

I thought it is supported out-of-the-box, as SimpleInjector preserves the scope from NetCore’s cross-wired service. It is also preserved in my case as each HTTP request ends up having a new instance of it, for example. However, it’s not acting like a scoped instance when trying to do some work inside the nested scope created via AsyncScopedLifestyle.BeginScope method. In that case, the same service acts as a “singleton” as I’m getting the same instance of the service.

I couldn’t find more thorough documentation about SimpleInjector nested scoping in conjunction with cross-wired scoped service (from IServiceCollection). So, would it be possible to give more insights into internal specifics or point me somewhere else, as it feels/sounds like a bug at this moment, although I guess it’s not the case.

Here is the setup:

public interface IScopedService { }
public class ScopedService : IScopedService { }

public class Startup
{
    private readonly Container _container = new Container();

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        services.AddScoped<IScopedService, ScopedService>();

        services.AddSimpleInjector(_container, opts =>
        {
            opts.AddAspNetCore().AddControllerActivation();
        });
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseSimpleInjector(_container);

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

As I found that when building API, here is a test controller used to show the behavior:

[ApiController]
[Route("")]
public class TestController : ControllerBase
{
    private readonly Container _container;

    public TestController(Container container)
    {
        _container = container;
    }

    [HttpGet]
    public async Task<bool> Get()
    {
        Debug.WriteLine($"Service : {_container.GetInstance<IScopedService>().GetHashCode()}");

        using (AsyncScopedLifestyle.BeginScope(_container))
        {
            Debug.WriteLine($"Service Scope 1: {_container.GetInstance<IScopedService>().GetHashCode()}");

            using (AsyncScopedLifestyle.BeginScope(_container))
            {
                Debug.WriteLine($"Service Scope 1.1: {_container.GetInstance<IScopedService>().GetHashCode()}");
            }
        }

        using (AsyncScopedLifestyle.BeginScope(_container))
        {
            Debug.WriteLine($"Service Scope2: {_container.GetInstance<IScopedService>().GetHashCode()}");
        }

        using (var scope = AsyncScopedLifestyle.BeginScope(_container))
        {
            Debug.WriteLine($"Service Scope 3: {scope.GetInstance<IScopedService>().GetHashCode()}");
        }

        return true;
    }
}

This is the output which I get:

Service : 47441805 Service Scope 1: 47441805 Service Scope 1.1: 47441805 Service Scope2: 47441805 Service Scope 3: 47441805

However, if I register the same service with Lifestyle.Scoped in SimpleInjector, I get the expected behavior and the following output:

Service : 6044116 Service Scope 1: 59817589 Service Scope 1.1: 48209832 Service Scope2: 5773521 Service Scope 3: 54135081

Usually, I’d just relocate registration to SimpleInjector, however what if we can’t do that easily, let’s say I want to take advantage of AddDbContext extension method to register DbContext. So, is there a way to configure/integrate those containers differently to allow nesting of cross-wired scoped service?

I’m using latest ASP.NET Core (3.1) and SimpleInjector (4.9)

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:8

github_iconTop GitHub Comments

3reactions
darjanbogdancommented, Jul 21, 2020

This is amazing, with such overload in place all the confusion (I had) around cross-wiring and scoping is gone, thank you again for all the effort!

1reaction
dotnetjunkiecommented, Jul 20, 2020

That absolutely makes sense and was already considering such construct.

Read more comments on GitHub >

github_iconTop Results From Across the Web

You are trying to resolve a cross-wired service, but are ...
You are trying to resolve a cross-wired service, but are doing so outside the context of an active (Async Scoped) scope. To be...
Read more >
Dependency injection guidelines - .NET
When designing services for dependency injection: Avoid stateful, static classes and members. Avoid creating global state by designing apps ...
Read more >
The dangers and gotchas of using scoped services in ...
In this post I look at the problems you can hit with strongly-typed settings when you inject Scoped services into IConfigureOptions, ...
Read more >
Dependency Injection Scope : r/dotnet
I'm having a hard time understanding the scoped instance. I'm comfortable with transient and singleton. What I don't understand about scope ...
Read more >
The Turtles Project: Design and Implementation of Nested ...
We show that despite the lack of architectural support for nested virtualization in the x86 architecture, efficient nested x86 virtualization— with as little...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found