IOC Container IDisposable Problem

620 views
Skip to first unread message

Mystagogue

unread,
Dec 3, 2009, 7:39:35 PM12/3/09
to structuremap-users
I have not yet used IOC containers, but I'm studying TDD and am
evaluating IOC container implementations (Castle Windsor, Autofac,
Unity, StructureMap, etc).

In general, I'm finding there is a noticeable problem regarding the
handling of IDisposable objects from an IOC container. The topic has
been discussed here:

http://stackoverflow.com/questions/987761/how-do-you-reconcile-idisposable-and-ioc

...but was not actually answered. I'm curious how StructureMap deals
with the problem.

The problem is that there is no way for a client class to know if an
injected dependency is IDisposable (without using reflection, which is
NOT acceptable). Instead, the IOC containers themselves implement
IDisposable and use reflection internally to determine which created /
provided objects are IDisposable. Thats good. However, the Unity
container doesn't keep track of most objects it creates - which makes
calling Dispose() on the Unity container near useless. Other
containers, such as Windsor and Autofac, keep track of *all*
IDisposable objects they make / contain. But even so, there is still
a problem. Calling Dispose() on those containers effectively ends the
lifecycle of the container, which leaves the client orphaned from
further IOC access. To compensate, the application code will often
post-pone calling Dispose() on the container as long as possible - the
opposite of what normally would be designed and coded.

If there is something I'm completely misunderstanding, please
explain. Otherwise, I'm hoping someone can discuss strategies that
minimize this problem.

Until that time, I'm considering either:
1) Don't use TDD / IOC containers. Instead use traditional testing
techniques (emphasis on component levelization and interface based
testing).
2) If using TDD / IOC containers, then:
a) don't use Unity (pick something else)
b) Never Resolve() on the parent container directly. Instead, every
recipient of the parent immediately makes a child container(s) and
calls resolve on that instead. When finished, the client always calls
Dispose() on the child container. So if there were any IDisposables
created, they are freed quickly.

My above solution #2 ASSUMES that the child container tracks objects
provided by Resolve(), even though the Register() may have been made
on the parent container.

In Summary: "tight" code and design presumes calling Dispose() the
moment a wrapped, non-managed resource is no longer needed. But the
design and code needs to *know* the wrapper contains a non-managed
resource in order to behave that way. With an IOC container, the
client code no longer knows if the injected object is wrapping a non-
managed resource. The story starts to devolve from that point
forward.

Jeremy D. Miller

unread,
Dec 3, 2009, 9:07:46 PM12/3/09
to structure...@googlegroups.com
Before I even address how StructureMap does it...

#1, these issues about both IoC or the disposable stuff are 100% orthogonal to TDD
#2, My strong feeling is that if you're designing your classes this should not be a problem at all.  Your services registered in the container should be cleaning themselves up internally on a call by call basis in the majority of cases.  Don't register something in the container that has to be disposed -- instead wrap the non-managed stuff in a .Net class that does the disposal stuff in the course of method calls.  Find a way to make your API support this model.  The only exception I can think of is long-lived services that use unmanaged resources.  Basically, the only place where this is a concern in my system is the NHibernate ISession. 

Now for StructureMap, the main container does NOT track transient objects because that's an awesome recipe for memory leaks.  If you were to choose the nested container approach that's in the StructureMap trunk, you could effectively use a "container per web request/transaction" scheme.  In this case, StructureMap tracks all the transient objects in the nested container, and calling Dispose on the nested container will also call Dispose on any child object created by that nested container.  You would still be responsible for disposing stuff that has non-managed resources that are long-lived, but there are some facilities to do that.  The nested container approach was largely developed for the NHibernate lifecycle management problem.

Jeremy D. Miller
The Shade Tree Developer
jeremy...@yahoo.com



From: Mystagogue <bar...@axiscode.com>
To: structuremap-users <structure...@googlegroups.com>
Sent: Thu, December 3, 2009 6:39:35 PM
Subject: [sm-users] IOC Container IDisposable Problem
--

You received this message because you are subscribed to the Google Groups "structuremap-users" group.
To post to this group, send email to structure...@googlegroups.com.
To unsubscribe from this group, send email to structuremap-users+unsub...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/structuremap-users?hl=en.



Reply all
Reply to author
Forward
0 new messages