The current project I'm working on requires a lot of nasty interop calls. The reason these calls are nasty is because they require a lot of manual garbage collection tweaking as well as specific disposal logic. Why it is required to mess with the GC is beyond the scope of this post. I'm trying to refactor some code in which there are dozens of similar instances that looks like this:
try
{
objA = InteropCallToCreateComObjBComObjA(someValues);
/* some null checking and validation code for objA */
objB = objA.InteropCallToCreateComObjB(someOtherValues);
/* some null checking and validation code for objB */
/* ... */
}
finally
{
//objB and objA cleanup code
}
objA's sole purpose is to provide a mechanism in which to create objB objects. objA is not used for any other purpose. objA may create one or more objB objects of different "types" (depending on the value passed into the constructor). These "types" all cast to the same .NET type but do different things under the hood. objA's life is generally the span of all objB's. Once all of objB's are cleaned up, objA is cleaned up (I'm not 100% sure if this is required, but that's how the code is written). So I thought I'd try and refactor to or towards the Factory pattern. Here's what I've come up with so far:
public class MyObjectFactory : IDisposable
{
InteropComA objA;
public MyObjectFactory(/*...*/)
{
objA = SomeInteropCallToCreateObjA(/*...*/);
/* some null checking and validation code for objA */
}
public InteropComB CreateObjB(/*...*/)
{
InteropComB objB = objA.CreateObjB(/*...*/);
/* some null checking and validation code for objB */
return objB;
}
public void Dispose()
{
// Clean up objA
}
}
This approach doesn't solve the entire problem. Currently all objB's are cleaned up and then objA gets cleaned up. I could create a wrapper for objB or modify the .NET interop class directly so that it implemented IDisposable. The implementing code would then look something like this:
using (MyObjectFactory factory = new MyObjectFactory(/*...*/))
{
using (disposableObjB = factory.CreateObjB(/*...*/))
{
// ugh, but sometimes I use different objB's in the same scope!
// using (someOtherObjB =... and so on, or I can just live with try...finally
// and call Dispose on each objB instance (there's usually one, a few at the most)
}
}
Now everything is disposed. The validation and disposal logic is contained within two classes: the object factory and the disposable version of objB. But there's a smell in the air and it's not because I'm sharing a 64sqft room with four developers. It isn't clear to me as an implementing developer that the factory is something that needs disposing. But then again the factories responsibility is to create objects which require some unmanaged resources in order to be created. What I would really like is to clean up all objB's, and then finally clean up objA like the code is currently doing. I'd like to do this without nested using statements, or without multiple calls to objB.Dispose() in a finally block. I can't do this in the factory because it is it is the responsiblity of the caller to dispose the object since it is the caller who will be using the object. The whole thing just seems a bit smelly to me.
Am I making a smell out of nothing, or am I just barking up the wrong pattern?