simpleinjector / SimpleInjector

An easy, flexible, and fast Dependency Injection library that promotes best practice to steer developers towards the pit of success.
https://simpleinjector.org
MIT License
1.21k stars 154 forks source link

Opt-out of `OnePerNestedScope` for scoped dependency #965

Closed Bouke closed 1 year ago

Bouke commented 1 year ago

I have a scoped dependency that I want to flow for the duration of the request / blazor circuit. I register it like this:

builder.Services.AddScoped<UserService>();
builder.Services.AddSimpleInjector(container,
    options => options.AddAspNetCore(ServiceScopeReuseBehavior.OnePerNestedScope));

This is working fine as long until I create nested scopes, as a new instance will be created inside that scope:

var root = container.GetInstance<UserService>();
using var scope = AsyncScopedLifestyle.BeginScope(container);
var nested = container.GetInstance<UserService>();
if (root != nested) throw new InvalidProgramException("The types should match");

I understand that this is caused by ServiceScopeReuseBehavior.OnePerNestedScope, which is needed in Blazor Server applications. So I need to keep using that behaviour, but I still want the ServiceScopeReuseBehavior.OnePerRequest behaviour for some of my scoped dependencies. How can I achieve this?

dotnetjunkie commented 1 year ago

There is a Scope.ParentScope property but it is currently internal. There's a feature request currently on the backlog for this.

You can, using Reflection, call this property, but.. of course at your own risk of breaking when upgrading Simple Injector.

You might otherwise be able to cache the service in a Blazor or ASP.NET Core cache to increase the lifetime of the service. Which cache to use, however, is hard for me to tell, because it depends on for how long you want to cache it. Might IHttpRequestAccessor give the right level of caching. You can cache items in the HttpContext.Items cache for the HttpContext returned by the accessor.