dongfo / autofac

Automatically exported from code.google.com/p/autofac
0 stars 0 forks source link

Suggestion: "Tree" lifetime #353

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
I have a suggestion that I believe will simplify lifetime handling in many 
situations.

In my application (a ASP MVC website) I have a lot of "utility" services that 
provide functions to higher-level services. Sometimes these utility services 
are used by page-generation services (with HTTP Request lifetime), but 
sometimes they're used by thread-pool background tasks (with their own lifetime 
scope), and sometimes they're used by SingleInstance services (such as caching 
services) that live forever. This makes it difficult to register the utility 
services with the container builder because their lifetimes vary according to 
the service they're being used by.

I'd like to propose a "tree" lifetime whereby a service is tied to the lifetime 
of its containing service, and then reused by any lower-level services. 
Consider the following registration:

builder.RegisterType<PageBuilderService>().InstancePerHttpRequest()
builder.RegisterType<WorkerService>().InstancePerLifetimeScope()
builder.RegisterType<LongRunningService>().SingleInstance()
builder.RegisterType<UtilityService1>().TreeLifetime()
builder.RegisterType<UtilityService2>().TreeLifetime()

Then, let's say PageBuilderService has the following structure:

PageBuilderService
  UtilityService1
  UtilityService2
    UtilityService1

In this example, UtilityService1 would be constructed only ONCE (because it has 
tree lifetime) and then both UtilityService1 and UtilityService2 will be 
cleaned up when PageBuilderService's lifetime ends (after the HTTP request).

Now, consider LongRunningService:

LongRunningService
  UtilityService2
    UtilityService1

UtilityService1 and UtilityService2 are constructed once and tied to the single 
instance lifetime of LongRunningService. This works without any tagging, 
naming, or anything else. 

Finally, consider WorkerService:

WorkerService
  UtilitySevice1

UtilityService1 is again constructed once and cleaned up when WorkerService's 
lifetime ends.

From what I can see, it would be very difficult to achieve this behavior using 
the current naming/tagging approach. Each utility service would need to be 
registered three times under different names/tags and the top-level services 
would have to be registered to choose the correct name/tag for the utility 
services they needed to use.

What I describe above is a common scenario, so I think this would be a valuable 
improvement to the codebase.

Thanks for a great effort! I use Autofac extensively and find it to be one of 
the best open source packages I've come across.

Original issue reported on code.google.com by mc...@carr-engineering.com on 18 Jan 2012 at 3:49

GoogleCodeExporter commented 8 years ago
Upon further investigation, I think I can achieve this by generically 
registering all my utility services with InstancePerLifetimeScope. This seems 
to work with all untagged, tagged, or container-based lifetime scopes. Am I 
understanding this correctly?

Original comment by mc...@carr-engineering.com on 18 Jan 2012 at 4:24

GoogleCodeExporter commented 8 years ago
Another question is how this should work when you have PageBuilderService and 
LongRunningService built from nested lifetimes. Would they (be able to) share 
the Utility services?

Original comment by david.black.co.at@gmail.com on 18 Jan 2012 at 7:11

GoogleCodeExporter commented 8 years ago
Hi there - yes, it sounds like what you're describing is 
InstancePerLifetimeScope(). Not sure about the second question, might be easier 
to construct a test case to validate it.

Original comment by nicholas...@gmail.com on 19 Jan 2012 at 6:15