I have some factory code along the lines of:
public MyHandlingClass Create()
{
var myHandler = new MyHandlingClass();
var myNotifier = new MyNotifyingClass();
myNotifier.Notify += myHandler.HandleNotification;
return myHandler;
}
The idea was to allow the MyHandlingClass
to react to external signals without caring about the type of the sender. In different applications the factory class containing the above method could then replace MyNotifyingClass
with something else able to raise a similar type of event.
In the actual code, the MyNotifyingClass
handles events from an unmanaged DLL:
public class MyNotifyingClass
{
private EventHandler notify;
private UnmanagedEventHandler unmanagedNotify;
public event EventHandler Notify
{
add
{
this.notify += value;
// Hold on to a strong reference to the delegate passed into the
// unmanaged DLL, to avoid garbage collection of the delegate:
this.unmanagedNotify = HandleUnmanagedNotify;
NativeMethods.SetNotifyCallback(this.unmanagedNotify);
}
remove
{
this.notify -= value;
}
}
private void HandleUnmanagedNotify(IntPtr sender, IntPtr eventArgs)
{
this.notify(this, eventArgs.Empty);
}
}
But when I return from the factory method, there are no longer any strong references to the myNotifier
instance, and it will eventually be garbage collected, resulting in access violations when my unmanaged DLL tries to invoke the callback.
I would like to somehow enforce that the myNotifier
instance has the same lifetime as the myHandler
instance. But I don't particularly like the idea of letting the MyNotifierClass
holding on to a strong reference to the handler object. After all, it has no further use for the actual object once the wiring is in place...
Can I somehow create a strong relationship between the two classes and still have them not know about each others existence?
(EDIT: To cut a long story short, this code snippet seems to reproduce my problem:)
[TestClass]
public class MyTests
{
public class MyHandler
{
public void Handle(object sender, EventArgs e)
{ }
}
public class MyNotifier
{
public event EventHandler Notify;
}
[TestMethod]
public void TestsSomeCondition()
{
var myHandler = new MyHandler();
var myNotifier = new MyNotifier();
myNotifier.Notify += myHandler.Handle;
var weakNotifierRef = new WeakReference(myNotifier);
myNotifier = null;
GC.Collect();
Assert.IsTrue(weakNotifierRef.IsAlive);
}
}