QWeakReferenceCollection
A commonly used technique to keep track of object instances is using a static collection to register these instances. For instance, in the Qios.DevSuite library each control has its own QColorScheme that the developer can change independently from other controls. There is also a QGlobalColorScheme that provides a way to change colors globally. Since the QColorSchemes do not change when the QGlobalColorScheme changes, all QColorSchemes are registered to the QGlobalColorScheme upon creation and a method of the QColorSchemes is called when the QGlobalColorScheme changes.
The problem with such a collection is that it keeps the collection members from being disposed (imagine a large control not being disposed because of one QColorScheme reference to the QGlobalColorScheme). We use a QWeakReferenceCollection to keep track of all QColorSchemes. All objects added to the QWeakReferenceCollection are wrapped in a QWeakReference and the QWeakReferenceCollection removes any disposed objects when iterating through the collection.
Show Code Snippet - Using a QWeakReferenceCollection
public class QColorSchemeCollection : QWeakReferenceCollection
{
public QColorSchemeCollection()
{
}
public void AddColorScheme(QColorScheme colorScheme)
{
this.AddObject(colorScheme);
}
public void RemoveColorScheme(QColorScheme colorScheme)
{
this.RemoveObject(colorScheme, true);
}
//Raises the ColorsChanged event of
public void RaiseColorsChanged()
{
QColorScheme tmp_oColorScheme;
for (int i = this.Count - 1; i >= 0; i--)
{
QWeakReference tmp_oReference = this[i];
if ((tmp_oReference != null) &&
(!tmp_oReference.Finalized) &&
(tmp_oReference.IsAlive))
{
//raise the event if the
tmp_oColorScheme = (QColorScheme)
tmp_oReference.Target
tmp_oColorScheme.RaiseColorsChanged();
}
else
{
this.RemoveAt(i);
}
}
}
}
QWeakMessageFilter
By using the IMessageFilter interface you can capture application messages before they are dispatched to the form or control. The application contains a list of all messages filters and that reference keeps the IMessageFilter from being disposed.
The QWeakMessageFilter is an intermediate class to make sure the actual IMessageFilter gets disposed when neccessary. The QWeakMessageFilter contains a QWeakReference to the actual message filter and only passes the message through if the QWeakReference has not yet been collected.
To implement a QWeakMessageFilter replace the following code:
Application.AddMessageFilter(m_oMyMessageFilter);
with:
Application.AddMessageFilter(
new QWeakMessageFilter(m_oMyMessageFilter));
Note: When calling the Application.AddMessageFilter to add a new IMessageFilter, the IMessageFilter is stored in the context of the current thread. The message filter cannot be removed from a different thread than the thread it was added from, therefore you cannot remove it via the finalizer. This is because the finalizer is called by the Garbage Collector and this happens in a different thread than the UI thread