LifetimeStyle limits the usefulness of Unity for custom lifetime management

Feb 16, 2008 at 12:58 AM
Edited Feb 16, 2008 at 5:24 PM
I will be the first to admit I have't fully walked through the code yet so if I am mistaken then please feel free to correct, flame, nuke, launch me into space, etc :)

I agree that the LifetimeStyle enum has the two most common lifetime styles that are used, the proverbial bread and butter of container lifetimes, per request (transient) and singelton.

However the limitation of using an enum as well as a use case specific method for lifetime management is limiting for many advanced use cases:

i.e. #1 Objects that should be shared across requests just like a singleton but available for garbage collection (e.g. weakreferenced). This is completely a requirement for many messaging systems wherein objects might need to be initialized as needed, are thread safe, but don't need to stick around in memory unless being actively used. (specification objects often fall into this category). I completely understand I can implement this functionality by writing a class that caches the inner type but isn't that really forcing me to muddle my model with extrinsic concerns?

i.e. #2 Objects that need to be throttled by the container. This is usually called pooling and something we've had in one of the first container systems, COM+. Again I can get the same result without much effort but I have to remind everyone Unity should be as transparent to my system as is possible.

Both of these are able to be done with ObjectBuilder (and I have) with policies and locators. we should open that expressiveness up to people that know what they are doing.

I am sure there are a million other potential variations on those themes and many many other use cases for lifetime management that are being used. Don't Mort me :)

Why do we have to jump through hoops for something like custom lifetime management. To me this is a first class concept in this problem domain. It would be very nice to be able to get an overload that acepts a lifetime manager that I can use to extend Unity without using two different ways of accomplishing the same task (e.g. SetSingleton and RegisterInstance). I am sure I can accomplish this with extensions and other methods but this seems like a code smell.

I'd argue that instead of SetSingleton<T>()/Registerinstance() overloads it makes more sense to have methods named SetLifetime<T>() with all the same overloads that SetSingleton() has now + 1 more, the one where I can pass in my own lifetime manager. I am also all for allowing easy "default" lifetime management strategies via that enum, but let it simple create a built in SingletonLifetimeManager or NullLifetimeManager for each appropriate use case and call the same overload that I can.

All in all though folks this is really starting to look good and am excited to see unity being available to the world. Keep up the good work!

Feb 16, 2008 at 1:17 AM
Thanks for the feedback, Jimmy. I have no intention of "Morting" you; whatever that means. ;-)

We definitely acknowledge the need for additional lifetime management styles. In the end, there just ended up being way too many of them. Rather than put in a plethora of stuff and potentially putting in stuff nobody would use, we decided to put in the bare minimum and wait for feedback. Which is now coming in, such as this post.

The OB expressiveness is available to those who know what they're doing via the container extension mechanism. This has the advantages of keeping the core interface dirt simple and letting the nascent community experiment a little before we bake this into the core container interface.

So, I'm sure you could imagine:

container.Configure<ILifetime>().SetLifetimeManager<Foo>(new ComPlusLifetimeManager(this, that, theother));

or something along those lines.

The container should absolutely be able to everything you described above, and they can all be done via the extension mechanism. Rather than add something now to the core container interface, I'd like to see if a general lifetime management extension evolves. Then, if it turns out to be something everyone likes, it can get promoted to the core container interface.

Does that sound reasonable?

Feb 16, 2008 at 2:28 AM
As previously posted, I've done the exercise of developing such a lifetime management.

I strongly believe SetSingleton should be ripped of the IUnityContainer interface and implemented using Configure<ILifeTime>().SetLifeTime(...)

Actually, IUnityContainer should be kept minimal to ease other implementations / decoration.

For shorter syntax (such as container.SetSingleton), I'd rely on extension methods...

The lifetime containers I've came up with so far:

PerAppDomain, PerApplication (web), PerContainer (singleton), PerRequest (web), PerSession (web), PerThread

Any other worthwile?
Feb 16, 2008 at 5:20 PM
Edited Feb 16, 2008 at 5:25 PM
>PerApplication (web), PerContainer (singleton), PerRequest (web), PerSession (web), PerThread

Agreed Francois! These are some great ideas and common lifetime management strategies you mention. :)

Just as an aside, I have seen many of these actually implemented in practice with a hierarchy of containers: One for the Application. One per session. One per Request (in the web that usually relates to per thread in practice)
All requests go to the lowest container at their level of responsibility (i.e. a WebForm event handler nabbing an object it needs from the thread container while an HttpModule would be at the application level perhaps). If the result cannot be fulfilled by the local container it goes up the hierarchy until the request can be fulfilled or it hits the top. Classic Chain of Responsibility pattern.

I just wanted to explicitly mention that that idea can be implemented in Unity as it stands today with support for a parent container. I feel it's such an important concept that it behooves me to mention it. :)


Feb 16, 2008 at 5:47 PM
I whole-heartedly agree with Francois' assessment. IUnityContainer should have no inherent concept of lifetime management, much less one specific lifetime management strategy. Lifetime management should be facilitated the exact same way any other creation stage strategy is handled ... through extensions.

It sounds like Francios, Jimmy, and I have each come to some similar conclusions about the singleton design choices. Each of us seems to dislike that Unity treats singletons as a special case. Francios and I are arguing that this should be done through extensions and should never be promoted to the IUnityContainer.

My reasons for this proposal really come down to my believe that the current approach lacks adherence to the principle of Separation of Concerns, specifically in reference to the areas of categorization and grouping. The concerns of managing objects as singletons aren't being grouped together with how you would do other types of lifetime management. Furthermore, if the IUnityContainer were to be broadened to mange the concerns of any style of lifetime management (e.g. through the use of the aforementioned SetLifetime methods), this would not group lifetime management concerns together with how other creation oriented things are managed (i.e. through extensions).

Jimmy, you mentioned that doing this through extensions seemed like a smell. I'm interested in hearing some elaboration on this if you could.

- Derek
Feb 16, 2008 at 6:03 PM
Edited Feb 16, 2008 at 6:19 PM

What I ment by that is that I would need to currently set singletons via an explicit method and all the other lifetime management strategies via extensions. Because I now have two ways to accomplish the same thing (or actually two paths of execution to accomplish what I feel is the same cross-cutting concern, Lifetime strategy of which Singleton is one concrete type) it's a code smell in the Api itself. Hopefully that's how a reader of my first post would take it (or if not then here's what i ment :))

Your statement "The concerns of managing objects as singletons aren't being grouped together with how you would do other types of lifetime management" is exactly my feeling as well; you've just more elegantly expressed it. :) I need to go drink more coffee before posting in the AM ha!

Now all that being said, I agree that this is completely a case where the implementation would be done via extensions. I think that usability is increased however by overloading the Register() method to allow a ILifetimeManger type as a parameter or express it as another method SetLifetime<T>(ILifetimeManager) in the Api (I guess that approach keeps the fluent interface fluent).

Francois is totally correct that extension methods would be the best way to extend the Api to make it easier to use for developer that would benefit from an say explicit method that allows them to mark a class as singelton. This is great because it allows a whole ecosystem to develop around "helpers". Keep Unity super clean and small for power programmers and map "helpers" to extension methods that can be included for those that benefit from them. This is not too disimilar to the whole nano/pico relationship, just now we have the power of extension methods that make this approach even more kick ass.

So basically something along the lines of a
using Microsoft.Practices.Unity.Extensions;

gives developers the myContainer.RegisterSingleton(type) methods when they benefit. All that's really doing is calling the approriate combination of methods on Unity to get the job done.
Feb 16, 2008 at 7:26 PM
Edited Feb 16, 2008 at 7:26 PM
Concerning the fluent interface, while I didn't do something as nifty as what Francois has described, my sample singleton implementation does preserve the fluent interface pattern:

             container = new UnityContainer()