seesharper/LightInject

Confusion: PerScopeLifetime or PerRequestLifeTime for request scoped services?

Shazwazza opened this issue ยท 6 comments

Hi,

I think this is more to do with documentation than anything but according to the docs for MVC it does state that registering controllers should be done with PerRequestLifeTime and then your (per request) services should be registered with PerScopeLifetime. And if you actually register your per-request services with PerRequestLifeTime you will actually get new transient instances per request instead of one per request which is all pretty confusing. The same thing goes for WebApi.

Between these 3 docs: https://www.lightinject.net/web/, https://www.lightinject.net/mvc/, https://www.lightinject.net/webapi/ there's a bit of inconsistency. There's only a single place that says you need to use PerScopeLifetime for services on a 'per-request' basis.

Is there a reason why declaring your services with PerRequestLifeTime doesn't actually only create one instance per request?

I can provide steps to reproduce if needed. This is using LI 5.5.0 and 2.0.0 of the web/mvc/webapi packages.

Thanks!

Just cross linking this description here umbraco/Umbraco-CMS#6044 (comment)

Would this be accurate?

  • PerRequestLifeTime is purely used to dispose objects created during a request at the end of the request, this doesn't mean they'll only be created once per request
  • PerScopeLifetime will only create one object per scope and dispose at the end of that scope and within the context of a request, the request is the scope.

But i'm just not sure that's really the intention and the docs here https://www.lightinject.net/#perrequestlifetime say

A new instance is created for each request

Which seems like it would indicate "once per request"?

Would this be accurate?

"PerRequestLifeTime is purely used to dispose objects created during a request at the end of the request, this doesn't mean they'll only be created once per request
PerScopeLifetime will only create one object per scope and dispose at the end of that scope and within the context of a request, the request is the scope."

Yes, that is correct. Although PerRequest might be a bit confusing in the context of MVC, it actually means that we get a new instance every time we request an instance from the container. It has nothing to do with the actual web request. So by "once per request", we mean " a new instance for each time the service is requested from the container"
In hindsight, the PerRequestLifetime might have had a better name, but we decided not to change it since we set the bar of breaking changes very high in LightInject:)

So the PerRequestLifetime behaves just like a transient with the only difference being that it is being tracked by the surrounding scope and instances created in that scope will be disposed when the scope ends.

Hope that al least makes some sense :)

Thanks for getting back to me, much appreciated!

No worries, i just needed to make sure i fully understood the difference - maybe i can send a PR to update the docs to make things a little clearer :)

But I do have one other question - I have tested registering all request based lifetime instances (i.e. one instantiation per request) including controllers using PerScopeLifetime and that works just fine. So to simplify our implementation, do you see any downside of also configuring controllers with PerScopeLifetime?

A PR for clarification would be great ๐Ÿ‘

any downside of also configuring controllers with PerScopeLifetime?

I got to admit it has been a while since I've worked with "legacy" MVC, but I seem to remember an issue with having them PerScopeLifeTime.
Maybe the MVC infrastructure in some situations can create two instances of the same controller? In any case, you should be okay with PerRequestLifetime since that also takes care of disposing disposables ๐Ÿ‘

Added more scoping documentation here ๐Ÿ‘
http://www.lightinject.net/#scope

fantastic thanks! ๐ŸŽ‰ :)