-
Notifications
You must be signed in to change notification settings - Fork 3
Description
Creating a AsyncScopedLifestyle scope inside of a ASP.NET Core web request does not result in a new scoped service when this service is resolved via Simple Injector ASP.NET Core cross wiring. Instead, it is resolving the same instance as in the other scope.
I could only reproduce this issue in a ASP.NET Core app, I have attached a solution (Cross wiring issue.zip) that demonstrates the issue.
Below a snippet that produces the issue:
Resolve using cross wiring
The CoreScopedService is registered in the ServiceCollection and cross wired using Simple Injector.
Throws because scopedService1 and scopedService2 are the same instance.
CoreScopedService scopedService1;
CoreScopedService scopedService2;
using (var scope = AsyncScopedLifestyle.BeginScope(Startup.Container))
{
scopedService1 = scope.Container.GetInstance<CoreScopedService>();
}
using (var scope = AsyncScopedLifestyle.BeginScope(Startup.Container))
{
scopedService2 = scope.Container.GetInstance<CoreScopedService>();
}
if (object.ReferenceEquals(scopedService1, scopedService2))
{
throw new InvalidOperationException("Same scoped service instance");
}The same scenario is working in the following cases:
Defer resolving the instances until after the web request
Does not throw, scopedService1 and scopedService 2 are separate instances.
Task.Run(() =>
{
// Sleep so resolving is done after the request has been completed.
Thread.Sleep(1000);
CoreScopedService scopedService1;
CoreScopedService scopedService2;
using (var scope = AsyncScopedLifestyle.BeginScope(Startup.Container))
{
scopedService1 = scope.Container.GetInstance<CoreScopedService>();
}
using (var scope = AsyncScopedLifestyle.BeginScope(Startup.Container))
{
scopedService2 = scope.Container.GetInstance<CoreScopedService>();
}
if (object.ReferenceEquals(scopedService1, scopedService2))
{
throw new InvalidOperationException("Same scoped service instance");
}
});Using SimpleInjector only
Does not throw, scopedService1 and scopedService 2 are separate instances.
SimpleInjectorScopedService scopedService1;
SimpleInjectorScopedService scopedService2;
using (var scope = AsyncScopedLifestyle.BeginScope(Startup.Container))
{
scopedService1 = scope.Container.GetInstance<SimpleInjectorScopedService>();
}
using (var scope = AsyncScopedLifestyle.BeginScope(Startup.Container))
{
scopedService2 = scope.Container.GetInstance<SimpleInjectorScopedService>();
}
if (object.ReferenceEquals(scopedService1, scopedService2))
{
throw new InvalidOperationException("Same scoped service instance");
}Using only ASP.NET Core DI
Does not throw, scopedService1 and scopedService 2 are separate instances.
CoreScopedService scopedService1;
CoreScopedService scopedService2;
using (var scope = _serviceScopeFactory.CreateScope())
{
scopedService1 = scope.ServiceProvider.GetRequiredService<CoreScopedService>();
}
using (var scope = _serviceScopeFactory.CreateScope())
{
scopedService2 = scope.ServiceProvider.GetRequiredService<CoreScopedService>();
}
if (object.ReferenceEquals(scopedService1, scopedService2))
{
throw new InvalidOperationException("Same scoped service instance");
}