Should factory keep track of created IDisposable objects?
Asked Answered
Q

5

8

Consider the following simple factory example:

public class MyFactory : IMyFactory
{
    public MyObject CreateObject()
    {
        return new MyObject();
    }
}

In this example, MyObject implements the IDisposable interface. Typically I would expect the consuming program to use this as follows:

// Use using to properly dispose of MyObject
using (MyObject obj = myFactory.CreateObject())
{
    // ...
}

Is it common practice to expect the developer consuming the Factory to handle disposal like this? Or should the Factory keep a list of objects it has created and make sure they are cleaned up periodically, or, possibly when the factory is disposed?

Quarta answered 18/12, 2014 at 6:16 Comment(1)
I think it would be safe to assume that the developer would take care of it. That is what we usually do while using the various Disposable objects that come out of the box in .Net (eg: Streams). The Factory on the other hand should limit it's functionality to Creating new instances of the objects, while the objects have IDisposable implemented.Yakutsk
Q
15

A type implementing IDisposable provides a way for the consumer of the type to deterministically clean up any unmanaged resources used by the type. E.g., when a FileStream is disposed the underlying OS file handle is closed.

Any properly implemented type that directly uses an unmanaged resource (e.g file handle, database connection, native socket etc.) will also have a finalizer to release the unmanaged resource when the object is garbage collected. It is up to the consumer of the type to either use IDisposable to deterministically release the unmanaged resource or simply wait for the garbage collector to do it. In most cases you want to go the deterministic route. E.g., you do not want to wait for the garbage collector before a file becomes accessible from other processes. You want to close the file as soon as you are done working with that file.

So the garbage collector in combination with finalizers will perform the task that you try to delegate to your factory and because your factory is not the garbage collector you will probably have a very hard time to actually implement this "tracking and automatic clean up".

So my primary answer to your question is, no, the factory should not keep track of created IDisposable objects.

However, if your factory is some sort of container that controls the lifetime of the created objects you can make the factory itself IDisposable and then dispose all created objects on disposal. This is a common pattern in dependency injection containers that are used in response-request cycles like in web applications. The container is created at the start of the request and disposed when the response is complete. The consumers of the types created by the factory are oblivious to the fact the some of the types have to be disposed when the request ends.

Quince answered 18/12, 2014 at 6:34 Comment(3)
While there's nothing wrong with this answer. I think it is worth mentioning that it's NOT uncommon to see Factory objects managing the life cycle of components. Especially when these components life cycle could vary...a transient object might not need to be manually disposed, but a singleton might need to be disposed. Bottomline is, it depends on your factory object's needsHalie
Oops, looks like my comment came a bit later than your edit :/Halie
@Leo: Yeah, Stack Overflow is a very dynamic place. :)Quince
F
1

"It depends"

When a factory creates IDisposable objects, it often makes sense for the client to dispose of them.

But a common factory pattern is to produce objects which are built using other disposables, but are not themselves disposable. Why would you do that? Because of the viral nature of IDisposable:

If you have a type that is composed out of 5 other inner types, and only the "inner most" is an IDisposable you have a choice:

  • you can implement the IDisposable pattern on all 5 types so that when you dispose of the "outer most" instance, the one genuine disposable get disposed correctly. This obviously requires a fair bit of cruft and affects the design of every type in your composition.
  • or, you can inject the one genuine disposable into your object composition from the factory, and let the factory manage the lifetime of the disposable. In this way the factory starts to fill more of a lifetime management role.

You do see examples of both approach in the real world, but I personally do not like implementing IDisposable just for viral reasons (i.e. my type is creating an IDisposable so must be IDisposable itself - as per .NET Framework Design Guidelines).

WCF's ChannelFactory keeps a list of all the channels it has created and closes them when you Dispose the factory. Similarly many IoC containers (which are themselves essentially super-factories) support a lifetime management role via things like StructureMap's GetNestedContainer() or Autofac's BeginLifetimeScope()

Finstad answered 16/11, 2016 at 5:31 Comment(0)
R
0

When you implement IDisposable you have to implement yourself the cleaning method for every class. In other words GC won't clean it for you properly leading to a memory leak.

Personally I recommend that every object who implements IDisposable should know how to clean itself.

If your factory creates and returns only instances without keeping list of each one, then each class which administrates external resources or unmanaged resources should implement IDisposable.

Raimund answered 18/12, 2014 at 6:37 Comment(0)
A
0

Absolutely NOT. Even in real world example, No real factory keep track of its products being trashed after their useful life.

Interesting, I was not assuming some technical discussions to a very simple question. In order to understand we have understand the analogy of the terms:

FACTORY: A term used to point to the object that is responsible for creating instances of types it can handle.

LIFE TIME MANAGER: A term used to point to the object that is responsible for the life time of the created instances. It usually work with more than one related instances, such as in the case of Dependency Resolver where it can dispose the dependency object as soon as the dependent object goes out of the scope.

Therefore, it would be better not to tie up so many things within a single class unnecessarily. I would appreciate the experts opinion on this.

Armistead answered 18/12, 2014 at 6:38 Comment(0)
K
0

If a factory does not trust that code using the objects it creates will reliably call Dispose upon them, it may be necessary to have the factory keep a link of weak references to such objects along with the information necessary to clean them up. That's an ugly pattern, but in some cases it may be better than any workable alternative if it's important to ensure that abandoned objects get cleaned up. While there are times when it's better to have the produced objects clean themselves up using destructors or Finalize, there are others when it's better to have the factory in charge of such cleanup. For example, if a factory's products subscribe to logical events from the factory, normal event subscriptions would keep those objects from ever getting finalized during the lifetime of the factory. If instead the factory keeps a list of WeakReference to such objects, each notification can cause all live objects to have their notification method invoked, and all dead objects to have their WeakReference removed from the list.

Kirov answered 14/11, 2016 at 16:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.