- 2012年2月11日 13:48
- CodeMemo | MVVM | Silverlight | Windows Phone 7 | WPF
Using the Model-View-ViewModel pattern, you always need to keep your events clean when they are not used(Especially ViewModel to View Event).
In example, Suppose the object “Foo” handles an event, when you finished using the Foo and forgot to release the event handlers,
the event would keep grabbing references to the Foo. This means that a memory leak is occurred.
If you are not familar with Weak Event patterns, this page would be helpful:
Weak Event Patterns
http://msdn.microsoft.com/en-us/library/aa970850.aspx
The above standard implementation, however, is not available in Silverlight or Windows Phone.
In addition, this mechanism(WeakEventManager and IWeakEventListener) is too cumbersome.
In the rest of this post, I propose a new implemention of it. This can be used in WPF, Silverlight, and Windows Phone 7.
I think that this is simpler and more intuitive than traditional ones.
In fact, this code is used in the “Livet” MVVM Framework, powered by Japanese MVVMers.
Usage Example
WeakEventManager and IWeakEventListener are not used.
public class Program { public static void Main(string[] args) { Program A = new Program(); var oldR = new WeakReference(new ReceiverOld(A)); var newR = new WeakReference(new ReceiverNew(A)); A.RaiseTestEvent(); //First //Exec GC GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); A.RaiseTestEvent(); //Second //--Result -- // // ReceiverOld Received ! // ReceiverNew Received ! // ReceiverOld Received ! // Console.ReadLine(); } private void RaiseTestEvent() { var handler = TestEvent; if (handler != null) { handler(this, new RoutedEventArgs()); } } public event RoutedEventHandler TestEvent; } //Normal Event Receiver Class public class ReceiverOld { public ReceiverOld(Program b) { b.TestEvent += OnTestEvent; } void OnTestEvent(object sender, RoutedEventArgs e) { Console.WriteLine("ReceiverOld Received ! "); } } //Event Receiver Class With LivetWeakEventListener public class ReceiverNew { LivetWeakEventListener _listener;//strong reference of listener public ReceiverNew(Program b) { _listener = new LivetWeakEventListener( h = > new RoutedEventHandler(h),//h is EventHandler h = > b.TestEvent += h, //h is RoutedEventHandler h = > b.TestEvent -= h, //h is RoutedEventHandler OnTestEvent); } void OnTestEvent(object sender, System.Windows.RoutedEventArgs e) { Console.WriteLine("ReceiverNew Received ! "); } } |
Source
Inspired by Observable.FromEvent Method Signature in ReactiveExtensions(Rx).
public class LivetWeakEventListener : IDisposable where TEventArgs : EventArgs { private bool _disposed = false; private EventHandler _handler; private THandler _resultHandler; private Action _remove; private static void ReceiveEvent(WeakReference listenerWeakReference, object sender, TEventArgs args) { var listener = listenerWeakReference.Target as LivetWeakEventListener; if (listener != null) { var handler = listener._handler; if (handler != null) { handler(sender, args); } } } private static THandler GetStaticHandler(WeakReference listenerWeakReference, Func, THandler> conversion) { return conversion((sender, e) = > ReceiveEvent(listenerWeakReference, sender, e)); } public LivetWeakEventListener(Func, THandler> conversion, Action add, Action remove, EventHandler handler) { if (conversion == null) throw new ArgumentNullException("conversion"); if (add == null) throw new ArgumentNullException("add"); if (remove == null) throw new ArgumentNullException("remove"); if (handler == null) throw new ArgumentNullException("handler"); _handler = handler; _remove = remove; _resultHandler = GetStaticHandler(new WeakReference(this), conversion); add(_resultHandler); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_disposed) return; if (disposing) { _remove(_resultHandler); } _disposed = true; } } |
If you have any problems, suggestions, or improvements on this code, feel free to leave a comment here.
コメント:0
トラックバック:0
- この記事のトラックバック URL
- http://ugaya40.net/codememo/an-implemention-of-weakevent-pattern-for-wpfsilverlightwindows-phone.html/trackback
- トラックバックの送信元リスト
- An implemention of WeakEvent pattern for WPF/Silverlight/Windows Phone - the sea of fertility より