namespace ConsoleApplication1
{
public class Program
{
public static void Main(string[] args)
{
Program A = new Program();
//本来メソッドスコープないの変数はメソッド中に
//回収される事はありませんが、
//WeakReferenceで囲う事でGCで回収可能にします。
var oldR = new WeakReference(new ReceiverOld(A));
var newR = new WeakReference(new ReceiverNew(A));
A.RaiseTestEvent();//1回目のイベント呼び出し
//ガベージコレクションの実行
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
A.RaiseTestEvent();//2回目のイベント呼び出し
//--結果 --
//
// ReceiverOld Received !
// ReceiverNew Received !
// ReceiverOld Received !
//
//2度目のイベント呼び出しではReceiverNewのイベントハンドラが呼び出されていない!
//
//GC後もProgram AがRecieveOldのイベントハンドラを参照しているから、
//oldAオブジェクトはGCに回収されていません。
//
//しかし今回の汎用WeakEventListenerを使ったnewAオブジェクトは見事回収されています。
Console.ReadLine();
}
private void RaiseTestEvent()
{
var handler = TestEvent;
if (handler != null)
{
handler(this, new RoutedEventArgs());
}
}
public event RoutedEventHandler TestEvent;
}
//通常通りイベントを受信しているオブジェクト
public class ReceiverOld
{
public ReceiverOld(Program b)
{
b.TestEvent += OnTestEvent;
}
void OnTestEvent(object sender, RoutedEventArgs e)
{
Console.WriteLine("ReceiverOld Received ! ");
}
}
//今回の汎用WeakEventListener使ってイベントを受信しているオブジェクト
public class ReceiverNew
{
LivetWeakEventListener<RoutedEventHandler, RoutedEventArgs> _listener;//リスナへの強い参照を保持
public ReceiverNew(Program b)
{
_listener = new LivetWeakEventListener<RoutedEventHandler, RoutedEventArgs>(
h => new RoutedEventHandler(h),//このhはEventHandler<RoutedEventArgs>
h => b.TestEvent += h,//このhはRoutedEventHandler
h => b.TestEvent -= h,//このhはRoutedEventHandler
OnTestEvent);//本来のハンドラ
}
void OnTestEvent(object sender, System.Windows.RoutedEventArgs e)
{
Console.WriteLine("ReceiverNew Received ! ");
}
}
}