WeakReference, I love you!
Un
In Windows Forms sfruttavo il fatto di poter realizzare un IComponent e avere gratis la chiamata a Dispose nel momento in cui veniva fatta la Dispose del componente contenitore, ad esempio la Form. In molti casi deviavo leggermente dal Dispose Pattern sfruttandolo per liberare anche risorse managed come ad esempio event handler.
Questo giochetto non funziona più! Osservate questo esempio:
Il “.net memory leak” è servito :-)var memento = new ChangeTrackingService(); var command = DelegateCommand.Create() .OnCanExecute( o => memento.IsChanged ) .OnExecute( o => { /* save pending changes */ } ) .TriggerUsing( MementoObserver.Monitor( memento ) );
Un monitor altro non è che un Observer che è capace di osservare uno specifico comportamento, nell’esempio un MementoObserver è un observer che è in grado di tenere d’occhio lo stato di un memento, more to come, e di triggherare la valutazione di un ICommand (CanExecuteChanged) al variare dello stato del memento, uno schiavetto con le mani in pasta da entrambe le parti :-)
Il problema sono proprio le mani in pasta da entrambe le parti… ampliamo un attimo lo scenario:
- Il memento sta mementando :-) una collection;
- La collection è una lista di qualcosa in binding con una ItemsControl di Wpf;
- La collection, per motivi storici e di compatibilità con Windows Forms, implementa IComponent;
- Sulla UI c’è un Button il cui Command è in binding con il command nel ViewModel;
- Il memento ha un trattamento speciale per gli IComponent;
- Il memento notifica le variazioni di stato con un evento TrackingStateChanged;
- Il MementoObserver ascolta l’evento di cui sopra, e trigghera il command;
- Quando un IComponent notifica di essere Disposed il Memento smette di tenerne traccia e notifica la sua variazione di stato, TrackingStateChanged, l’observer se ne accorge e trigghera il command;
WeakReference
la salvezza è usare una WeakReference per tutti quegli scenari in cui sia necessario avere una reference a qualcosa su cui non si ha un controllo diretto. In questo caso infatti il MementoObserver deriva da una classe astratta che incapsula il concetto di WeakReference all’elemento monitored e si preoccupa di gestirne il lifetime garantendo la consistenza.
.m