Should the factory keep track of the generated IDisposable objects?

Consider the following simple factory example:

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

      

This example MyObject

implements the interface IDisposable

. I usually expect the consumer program to use it like this:

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

      

Is it common to expect a developer consuming a factory to handle deletion like this? Or should the factory keep a list of the objects it created and make sure they are cleaned up periodically, or perhaps when placing the factory?

+3


source to share


5 answers


Type injection IDisposable

provides a way for the consumer of a type to deterministically clean up any unmanaged resources used by the type. For example, when a is FileStream

allocated, the OS main file descriptor is closed.

Any properly implemented type that directly uses an unmanaged resource (such as a file descriptor, database connection, native socket, etc.) will also have a finalizer to release the unmanaged resource when the object is garbage collected. For a consumer of a type, use either IDisposable

to release an unmanaged resource deterministically or just wait for the garbage collector to do so. In most cases, you want to follow a deterministic route. For example, you don't want to wait for the garbage collector before the file is available from other processes. You want to close the file as soon as you are done with that file.

So, the garbage collector combined with the finalizers will accomplish the task you are trying to delegate to your factory, and because your factory is not a garbage collector, you probably have a very difficult time implementing this "tracking" and automatic cleanup.



So my main answer to your question is: no, a factory shouldn't keep track of objects created IDisposable

.

However, if your factory is some sort of container that manages the lifetime of the created objects, you can make the factory itself IDisposable

and then destroy all the created objects in your possession. This is a common pattern in Dependency Injection containers that are used in response request loops such as web applications. The container is created at the beginning of the request and removed when the response is complete. Consumers of types created by a factory are oblivious to the fact that some of the types must be disposed of when the request completes.

+7


source


"It depends on the

When a factory creates objects IDisposable

, it often makes sense for the client to dispose of them.

But the generic factory pattern is for creating objects that are created using other consumables but are not available on their own. Why would you do this? Due to the viral nature IDisposable

:

If you have a type that consists of 5 other inner types, and only the "inner majority" is that IDisposable

, you have a choice:



  • you can implement a pattern IDisposable

    for all 5 types so that when you delete an instance of the "outermost" one true disposable is properly installed. This obviously requires a fair cue ball and affects the design of every type in your composition.
  • or you can inject one genuine disposable into your composition object from the factory and let the factory manage the lifetime of the disposable. So the factory starts filling more of the lifecycle management role.

You see examples of both approaches in the real world, but I personally don't like the implementation IDisposable

just for viral reasons (i.e. my type creates IDisposable

, so there should be IDisposable

.NET Framework Design Guidelines on its own).

WCF ChannelFactory

keeps a list of all created channels and closes them when you Dispose

factory. Likewise, many IoC containers (which are essentially superfactors) support the role of lifetime management through things like StructureMap GetNestedContainer()

or AutofacBeginLifetimeScope()

+1


source


When you implement IDisposable

, you need to implement a cleanup method for each class. In other words, GC

won't clear it for you, which will result in a memory leak.

Personally, I recommend that every object that implements IDisposable

should know how to clean itself up.

If your factory only creates and returns instances without keeping a list of each, then every class that administers external resources

or unmanaged resources

should implement IDisposable

.

0


source


Absolutely NOT. Even in the real world, for example, no real factory keeps track of their products to be destroyed after their useful life.

Interestingly, I didn't accept some technical discussion on a very simple matter. To understand that we understand the analogy with the terms:

FACTORY: A term used to indicate an object that is responsible for instantiating types that it can handle.

TIME MANAGER: A term used to indicate an object that is responsible for the lifetime of instantiated instances. It usually works with more than one related instance, such as in the case of Dependency Resolver, where it can remove the dependency object as soon as the dependent object goes out of scope.

Therefore, it would be better not to bundle so many things in one class unnecessarily. I would appreciate it by an expert.

0


source


If the factory does not trust that code using the objects it creates will reliably call Dispose

them, it may be necessary for the factory to retain a weak reference to such objects along with the information needed to clean them up. This is an ugly model, but in some cases it may be better than any acceptable alternative if it is important to clean up abandoned facilities. While there are times when it is better to have produced objects cleaned up using destructors, or Finalize

there are others when it is better to have a factory in charge of such cleanup. For example, if factory products subscribe to boolean events from a factory, regular event subscriptions will allow those objects to be finalized over the life of the factory. If instead the factory stores a listWeakReference

for such objects, each notification can cause the notification method to be called for all living objects, and all dead objects will be removed from WeakReference

the list.

0


source







All Articles