JasperFx / lamar

Fast Inversion of Control Tool and Successor to StructureMap
https://jasperfx.github.io/lamar
MIT License
563 stars 118 forks source link

Injecting Func<IScopedService> into Singleton behaviour #280

Closed JulianKlauser closed 3 years ago

JulianKlauser commented 3 years ago

We noticed this issue when transitioning from StructureMap that this works differently in Lamar. We observed this within an Asp.Net Core Application: When injecting a Func<IScopedService> into a Singleton, the injected Func starts behaving like a Singleton (only one instance of the scoped service gets created when calling the func - over multiple requests). Injecting a Func<ITransientService> works as expected (a new instance every time the func is called).

Is this behaviour intended or a bug?

9ParsonsB commented 3 years ago

I can confirm this behavior and that it was not what I was expecting. My use case is that I have added a database (EFCore) service as scoped and am trying to access that from a singleton.

Whenever I try and access the database after the initial construction, it is disposed.

jeremydmiller commented 3 years ago

@JulianKlauser @9ParsonsB "Scoped" means that it's scoped to the container that created it. If you're resolving a singleton, you're resolving the singleton from the root container, which means the Func<IScopedService> is also scoped to the root container. So long winded way of saying that that's expected behavior.

If you need to control the lifecycle and use multiple IScopedService within the singleton, my advice is to explicitly create new scoped containers, then resolve from that scoped container. So either natively with Lamar's IContainer.GetNestedContainer() or the .Net Core IServiceProvider.CreateScope() (which is still a Lamar nested container in this case)

jeremydmiller commented 3 years ago

And sorry for the delay getting around to this:(

JulianKlauser commented 3 years ago

Thanks for the explanation and provided solution. Makes sense when you think about it, it just caught us unaware during the transition.