View Full Version : Spring.Objects.Factory.IDisposableObject vs System.IDispose
Anonymous
12-09-2004, 07:28 PM
One of the things I really like about Spring is that it works transparently with plain objects without forcing you to use its own APIs.
Now I look at Spring.Objects.Factory.IDisposableObject and I see that it is semantically identical to System.IDispose.
The obvious question is why create a new interface for something that the platform already provides? Was it done intentionally or is it just an oversight?
The spring factory has two way of cleaning things up - call Destroy on all IDisposableObjects and call the "destroy-method" defined in xml.
Seems to me it wouldn't be unreasonable to assume that for objects implementing IDispose the Dispose method would be invoked automatically.
What do you think?
Rick Evans
12-10-2004, 12:27 PM
Mmm... is the System.IDispose interface really semantically identical to the Spring.Objects.Factory.IDisposableObject (http://www.springframework.net/doc/api/Spring.Objects.Factory.IDisposableObject.html) interface?
Although interfaces cannot (obviously) mandate behaviour, the MSDN docs (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconimplementingdisposemethod.asp) strongly recommend that one calls the GC.SuppressFinalize method in a class that implements the IDispose interface... this, to my mind, strongly links the System.IDispose interface to the lifecyle of an object in the .NET runtime and it's attendant garbage collection routines. That is, Dispose () is linked with an object that is about to be purged from memory.
The Spring.Objects.Factory.IDisposableObject (http://www.springframework.net/doc/api/Spring.Objects.Factory.IDisposableObject.html) interface links an (arbitrary) object to the lifecycle of an object in a Spring.NET container (factory / context)... and an object may well continue to exist (as an entity in the .NET runtime) long after the Spring.NET container from which it was pulled has been shut down.
Consider the case where (I) instantiate a Spring.NET ApplicationContext style container, pull some objects out of it with all of their dependencies nicely taken care of, and then dispose of the container since I don't need it anymore. In this case the Spring.Objects.Factory.IDisposableObject (http://www.springframework.net/doc/api/Spring.Objects.Factory.IDisposableObject.html) will be called (and any destroy method that I have specified in my Spring.NET configuration) when the container is shutdown, but I don't want the IDispose method to be called on my objects, since I'm about to go off and use them.
Hence the distinction betwen the two interfaces, and the need for a separate interface (namely the aforementioned Spring.Objects.Factory.IDisposableObject (http://www.springframework.net/doc/api/Spring.Objects.Factory.IDisposableObject.html) interface).
Anonymous
12-10-2004, 07:12 PM
Consider the case where (I) instantiate a Spring.NET ApplicationContext style container, pull some objects out of it with all of their dependencies nicely taken care of, and then dispose of the container since I don't need it anymore. In this case the Spring.Objects.Factory.IDisposableObject (http://www.springframework.net/doc/api/Spring.Objects.Factory.IDisposableObject.html) will be called (and any destroy method that I have specified in my Spring.NET configuration) when the container is shutdown, but I don't want the IDispose method to be called on my objects, since I'm about to go off and use them.
Well, I thought of that and yes I understand that there would be a distinct behaviour on the container's part.
However I find the scenario you're describing very difficult to code reliably.
The component developer needs to know that Destroy is more of a OnContainerDestroy and keep the component in perfect working condition just in case the client code wants to keep using it (something which by the way it has no way of finding out).
The client code cannot really assume that it's safe to keep using the component after releasing the container because it doesn't know if and how the component implements lifecycle methods.
I think a far safer way to accommodate your scenario would be for the client code to explicitly tell the container not to apply the cleanup to a particular instance. Something like "detach from parent" or "suppressDestroy".
This way the client code gets direct control over the lifecycle which is what we want, right?
At the same time the component developer does not face the decision of putting the cleanup code in Dispose vs Destroy (I'm not sure how I would make that decision myself) and better yet doesn't have to know a thing about Spring and still count on resources being cleaned-up timely.
Mark Pollack
12-11-2004, 12:01 AM
Hi,
Just to clarify on the lifecycle usage in Spring. The destroy lifecycle callback only applies to objects that are declared as singletons. If you specify singleton='false' in the configuration, this is equivalent to performing a standard 'new', Spring doesn't keep track of the object instance, and client code has direct control over the lifecycle. In the case of a singleton, the container keeps a reference to the object instance so that it can return the same instance over and over again.
So the questions then is really what to do in the case of singleton usage for a class that implements IDisposable. In most apps I've seen the app context/IoC container is created on application startup and destroyed when it exits - making the automatic calling of IDisposable's Dispose method appropriate. However, in the future we may introduce more dynamic behavior to the app context where the distinction of lifetime in the container vs. lifetime in the process memory may be important. It is certainly worth debating about some more...
Cheers,
Mark
Aleks Seovic
12-12-2004, 12:27 AM
I think that we should drop IDisposableObject, which was used in Spring.Java and use IDisposable for Spring.Net. Last week I incorrectly assumed that's how current container works and got very confused when Dispose wasn't called on exit.
Scenario that Rick is describing is very unlikely, and the benefit of using standard .Net interface is that all standard .Net classes that implement IDisposable will be properly managed by the container.
Java team didn't have IDisposable equivalent in JDK, so they had to come up with something that will accomplish the same goal, but I don't think we need two ways to do the same thing in Spring.Net (and I do agree that those two interfaces are semantically identical, as Alex mentioned).
If we do need to handle a case where container is unloaded but we still need to keep objects around in the future (and I can't think of a case where we would need that, to be honest), we can come up with something that clearly differentiates that case from the objects that implement IDisposable (such as Unload event on the container that interested objects can listen for).
-- Aleks
Griffin Caprio
12-12-2004, 06:25 PM
I agree with Aleks. +1 for using IDisposable.
Also, just a bit of clarification about what Rick said about IDisposable. The MSDN docs advocate calling GC.SuppressFinalize only when the object implements a finalizer.
Objects that implement a finalizer are placed in a finalization queue. If an object is disposed of by calling it's Dispose() method, the GC.SuppressFinalize() call removes the object from the finalization queue, so it's not clean up twice.
Rick Evans
12-13-2004, 08:26 AM
Fair dues... I didn't infer that the DisposableBean interface from the Spring.Java source was intended to be called when the JVM was shutdown; I thought it was strictly for container shutdown :( . So, +1 for dropping the IDisposableObject interface.
But I'd also raise the issue that whether or not the Dispose method of the IDisposable interface should be called automatically on container shutdown is something that should perhaps be left to the (application) developer, and not assumed by the (framework) developer... that way the application developer can decide whether or not he / she wants Dispose called when the container is destroyed
To wit... if I want my managed object's Dispose method to be called on container shutdown, this is purely a configuration issue where (in the current XML implementation) I simply add destroy-method="Dispose" attributes to all of my singleton object definitions.
Tool support is something that would be a great boon in this regard, because admittedly, having to add destroy-method="Dispose" attributes to each and every one of singleton object definjtions if this is the behaviour that I want would be a pain.
Anonymous
12-13-2004, 04:42 PM
To wit... if I want my managed object's Dispose method to be called on container shutdown, this is purely a configuration issue where (in the current XML implementation) I simply add destroy-method="Dispose" attributes to all of my singleton object definitions.
Tool support is something that would be a great boon in this regard, because admittedly, having to add destroy-method="Dispose" attributes to each and every one of singleton object definjtions if this is the behaviour that I want would be a pain.
Well that and the fact that by requiring "destroy-method" you place the cleanup responsability on the developer who uses the class, meantime surprising the developer who wrote it by not automatically calling Dispose as soon as you don't need the instance.
I think Aleks put it best when he pointed out that the reason for having DisposableBean in Java was that the JDK didn't have an equivalent so the Spring team had to come up with something.
In .NET the wheel has already been invented.
vBulletin® v3.7.3, Copyright ©2000-2009, Jelsoft Enterprises Ltd.