У меня есть некоторый заводской код в соответствии с:
public MyHandlingClass Create()
{
var myHandler = new MyHandlingClass();
var myNotifier = new MyNotifyingClass();
myNotifier.Notify += myHandler.HandleNotification;
return myHandler;
}
Идея состояла в том, чтобы позволить MyHandlingClass
реагировать на внешние сигналы, не заботясь о типе отправителя.В различных приложениях фабричный класс, содержащий вышеупомянутый метод, может затем заменить MyNotifyingClass
чем-то другим, способным вызвать событие аналогичного типа.
В реальном коде MyNotifyingClass
обрабатывает события из неуправляемой 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);
}
}
Но когда я возвращаюсь из фабричного метода, больше нет сильных ссылок на экземпляр myNotifier
, и он в конечном итоге будет собирать мусор, что приведет к нарушениям доступа, когда моя неуправляемая DLL пытаетсявызовите обратный вызов.
Я хотел бы каким-то образом принудительно установить, что экземпляр myNotifier
имеет то же время жизни, что и экземпляр myHandler
.Но мне не особо нравится идея позволить MyNotifierClass
держаться за сильную ссылку на объект-обработчик.В конце концов, он больше не будет использоваться для реального объекта после того, как проводка будет на месте ...
Могу ли я каким-то образом создать прочные отношения между двумя классами и при этом заставить их не знать о существовании друг друга?
(РЕДАКТИРОВАТЬ: Короче говоря, этот фрагмент кода, похоже, воспроизводит мою проблему:)
[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);
}
}