Problem example IDisposable template?

Let's say you have 3 classes that implement IDisposable - A, B and C. Classes A and B depend on class C.

  • Would it be correct to say that a typical Dispose () implementation of classes A and B:

    public void Dispose() { if (m_C != null) m_C.Dispose(); } 
  • If there is an instance of A and an instance of B that use the same instance of C, how would you overcome the problem that saved instance A from instance B?

  • The last sentence - if in paragraph 2 it is a DI container that creates instances of all instances that are responsible for deleting objects? Is this the container itself? How?

Thanks Urig

+6
c # dependency-injection inversion-of-control idisposable
source share
10 answers

The layout is based on an established “owner” who decides when a resource should be deleted.

If A and B must refer to the same instance of C, then only one of them must act as the "owner".

While you can do link counting, I usually find it best to document who “owns” that. For example, when you create a Bitmap with a stream, a stream belongs to Bitmap from this point, and you do not have to manage it yourself. This may cause several problems, but in the end it is easier than trying to even out the reference count.

+12
source share

Performing a null check will not help, as if B had C, it would not update the link.

You must ensure that only one of the classes owns C. This owner class is then responsible for removing it.

Typically, the class creating C should be the class that uses it.

+4
source share

Only one copy must be the owner, and he is responsible for the removal. A non-owner instance must obtain a reference to C using a function such as Attach and must not dispose of it.

+1
source share

Who created the instance? This is usually the owner and should be responsible for deleting the instance.

Most likely, you have an “external” class that created C, and then passed it directly or indirectly to A and B. It is probably a natural candidate who is responsible for and must manage the C life cycle.

[Edit: in response to OP comment] Sounds like maybe you should take a look at the design here. Does this indicate the need for a refactor?

You have a class C that needs to be disposed of, which is used by both A and B; if you have a class that has a common responsibility for sorting C through A and B, and not for creating C from a DI container? Or C is really more singleton. Does it really need to be disposed of?

I assume that all I am saying is that it looks like it can point to a design that needs a little change; have a different look with a critical eye.

+1
source share

The last addition - if in paragraph 2 it is a DI container that creates all the authorities responsible for deleting objects? Is it the container itself? How?

Yes, the container has all the IDisposable objects that it creates. A container has these objects when it is located on its own. All DI containers should already do this by default.

Sometimes a DI framework gives you the opportunity to take responsibility. For example, in Autofac, you can request the input Owned<T> , and then you can safely call Owned<T>.Dispose() yourself when you're done with the object. This is especially useful if you dynamically create instances using the Func<Owned<T>> factory you entered. Please note that such “owned instances” are not intended to be shared.

+1
source share

Two methods I could think of:

  • Create a parent collection inside C and in the delete method A and B, remove yourself from the child parent collection. Then, if the count of the parent collection is 0, call dispose.
  • Lazy loads the property within A and B for access C. Perform a zero check on C, if any other object destroyed it, restore it (if possible).
0
source share
  • Usually I do it the way it is usually accepted, and it definitely works. However, if another object deleted it, checking for zero will not stop calling the call because it will not be zero. C should be protected from multiple calls.

  • Very good question. Right away, what comes to mind should be the logic to know how many points are currently at this facility, so it can control its disposal methods. Semaphores do this, but are heavy.

I would also ask where you see this in the real world, there may be a design mismatch. Update: as mentioned in other documents, this comes down to a design problem - you get a similar effect when using CCW, someone else releases a basic COM object where other users can use it.

0
source share

This will be the correct implementation: however, you can save links to all objects depending on a specific instance of C both A and B , and also check that this list is empty (except for the current object) in the C Dispose method.

0
source share

In addition to what John said, the creator is the owner and must be disposable.

In this case, it is a container, and the container is responsible for removing the components. Not every component supports this (or at least not all). Windsor Castle does . Autofac also supports it.

0
source share

Each IDisposable must have one owner. If the resource will need to be used for several users, any of which may be the last to use it, then each user must have a link to his own shell. Then, wrapper objects must use some means other than IDisposable to coordinate with one private created inner-shell object, which then calls the Dispose resource. An internal wrapper object does not need to use IDisposable for cleaning, since it is not published, and the fact that it should not use IDisposable means that it can use a cleaning tool that hosts several owners.

0
source share

All Articles