Sunday, May 2, 2010

Dispose Complete Hierarchy


While working with a family hierarchy of a class, I was trying to optimize the memory usage because there was a case reported in one of the tools that worked on that the data loaded in memory was using up all the RAM. I worked on the case and found that the custom classes that were written for the project were not disposable. This leaves memory freeing job to Garbage Collector, and its not best decision sometimes.

I wrote two classes for making disposing of objects easy. NayanTools.Dispose method is the core of disposing engine.

One thing that you need to keep in mind while using this function, it will dispose the member objects of the object you pass to it, as well as, it will go in recursion - provided all those classes are implemented from AbstractDisposingClass.

So, the implementation of a disposable class using AbstractDisposingClass should look like -

01 class A : AbstractDisposingClass {
02 ~A() {
03 dispose(false);
04 }
05 };


The usage is simple, as you dispose any other class-
A n = new A();
n.Dispose();


A bit more complex example will be -
01 class A : AbstractDisposingClass {
02 List<string> jjj = new List<string>();
03 ~A() {
04 dispose(false);
05 }
06 };
07
08 class B : AbstractDisposingClass {
09 string test = string.Empty;
10 List<string> hello = new List<string>();
11 List<A> allo = new List<A>();
12 Dictionary<int, int> ddd = new Dictionary<int, int>();
13 public B() {
14 allo.Add(new A());
15 }
16 ~B() {
17 dispose(false);
18 }
19 };
20
21 ...
22
23 private void destroyExample () {
24 B n = new B();
25 n.Dispose();
26 }


Here is the code for the classes and methods.


01 using System.Collections;
02 using System.Reflection;
03 ...
04 public static class NayanTools {
05 public static bool IsList (object obj) {
06 IList list = obj as IList;
07 return list != null;
08 }
09
10 public static bool IsCollection (object obj) {
11 ICollection coll = obj as ICollection;
12 return coll != null;
13 }
14
15 public static bool IsDictionary (object obj) {
16 IDictionary dictionary = obj as IDictionary;
17 return dictionary != null;
18 }
19
20 public static void Dispose (bool bNotDisposed, object _object) {
21 if (bNotDisposed && _object != null) {
22 Type type = _object.GetType ();
23 FieldInfo[] arrayFI = type.GetFields (BindingFlags.FlattenHierarchy|BindingFlags.GetField|BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public);
24 foreach (FieldInfo fieldInfo in arrayFI) {
25 object fieldObject = fieldInfo.GetValue (_object);
26 if (fieldObject != null) {
27 if (NayanTools.IsDictionary (fieldObject)) { //key-value type collection?
28 IDictionary dictionary = fieldObject as IDictionary;
29 foreach (object _ob in dictionary.Values) {
30 if (_ob is IDisposable && _ob != null) {
31 IDisposable _disposeableObj_ = _ob as IDisposable;
32 _disposeableObj_.Dispose ();
33 }
34 }
35 dictionary.Clear ();
36 }
37 else {//normal collection
38 if (NayanTools.IsCollection (fieldObject)) {
39 ICollectioncoll = fieldObject as ICollection;
40 foreach (object _ob in coll) {
41 if (_ob is IDisposable && _ob != null) {
42 IDisposable _disposeableObj_ = _ob as IDisposable;
43 _disposeableObj_.Dispose ();
44 }
45 if (NayanTools.IsList (fieldObject)) {
46 IList list = fieldObject as IList;
47 list.Clear ();
48 }
49 }
50 }
51 }
52 if (fieldObject is IDisposable) {
53 IDisposable _disposeableObj = fieldObject as IDisposable;
54 _disposeableObj.Dispose ();
55 }
56 fieldInfo.SetValue (_object, null);
57 }
58 }
59 }
60 }
61 }
62
63 [Serializable]
64 public abstract class AbstractDisposingClass : IDisposable {
65 [field:NonSerialized]
66 protected bool m_IsDisposed = false;
67
68 public virtual void Dispose () {
69 dispose (true);
70 GC.SuppressFinalize (this);
71 }
72
73 protected virtual void dispose (bool bNotDisposed) {
74 if (!m_IsDisposed) {
75 m_IsDisposed = true;
76 NayanTools.Dispose (bNotDisposed, this);
77 }
78 }
79 }

Auto Save in Paint - ver 1.6

This is latest version of AutoSavePaint application. Nothing major, but some fixes.

Fixes
  1. Busy icon was not properly showing. Fixed now.
  2. The icons to show the job status (red, green, orange) were not properly showing sometimes. Fixed.

The next version will take some time as there is nothing much to be fixed right now. And I have to think about new features (I don't have any idea!) =)

If you would like to see some better changes, please provide feedback.

Updated Download Link: Auto Save in Paint 1.6

Update 1-Aug-2010:
I have tested and experimented this tool on Win XP, and it works great. But after trying it on Win 7, it seems that the Paint application of Win 7 works differently. The results can be opposite. I observed a 41 KB JPEG file turning to 62 KB after saving it.

This tool works fine. Since it is dependent on external application (Paint here), the saving algorithm may vary, and so do the results.