lundi 30 mars 2009

Static event on ViewModel in MVVM : Helper that prevents Leak errors memory, and so more …

Abstract

Use static public event properties on ViewModel class for :

  • High level of API to mask the technical complexity of the problem
  • ensure communication between ViewModel and View part without leak memory AND with only one wired process on View part even if ViewModel contains lot of entities.
  • ensure communication between entities of ViewModel and ensure it in a graph of entities.
  • accept lot of quantity of ViewModel entities without overhead (memory or/and performance)
  • controls target’s type which is allowed to use on these events

Introduction

In MVVM architecture, I need create a graph of entities in ViewModel part with POCO objects. these entities must communicate with …

  • another instances of ViewModem
  • View part of the MVVM architecture

… without direct dependency between Sender to the targets : ViewModel has not dependency on "View Part" AND sometimes, entities of ViewModel  do not link directly all another entities of the model

A good technical approach to do this is used a static CLR Event on ViewModel class, static events are always accessibles even if ViewModel instance not yet exists

  • from another ViewModel class
  • from “View part“ of MVVM like a Window or UserControl.

BUT we need integrate these contraints :

  • a Simple static CLR Event keeps a reference on target’s instance : Garbage collector will never free target’s instance if this target will not remove its handler in the static CLR event.
  • If static CLR event is used by a lot of quantity of ViewModel instance. The performance must stay high.
  • If we create more than one instance of the ViewModel graph and use only static CLR Event : Each Invoke of static event must reach only the “good” instances of ViewModel (or View part) and not all referenced target.

“Good” instances seems only ViewModel entity that have relations with the invoker ViewModel OR View part that bind with ViewModel entity.

I proposed a main class : StaticEvent<> that can help us to do this !

How can I use it ?

Example of code to declare a new Event :

private static StaticEvent<MyEventArgs> _myEvent = 
  new  StaticEvent();
public static event EventHandler<MyEventArgs> MyEvent
{
  add
  {
    _myEvent.Add(value); 
  }
  remove
  {
    _myEvent.Remove(value);
  }
}

public static void OnMyEvent(MyEventArgs e)
{
  _myEvent.Invoke(e);
}

When developper uses the event : he works with it like a classic event with += / –= operator. The internal implementation is masked.

What can I wired on this type of Event ?

StaticEvent<> generic class is a base class to implement another type of it. In Diagram class below, and the prototype, I used a ModelViewEvent<>.

This event accepts 3 types of EventHandler :

  • EventHandler on a static method
  • EventHandler on an instance entity of ViewModel
  • EventHandler on an instance of FrameworkElement.

Entities of ViewModel must derivated from ViewModelBase<> class that implements required interface (IHandlersRepository)

The sequence of calls during “Invoke process”

The main concept is base on RoutedEvent of WPF framework. In the RoutedEvent design pattern : the “route” of calls is build BY the invoker !

I was reproduce the same approach in StaticEvent class !

If the invoker is a ViewModel Entity (supports IHandlersRepository), StaticEvent asks the invoker (by IHandlersRepository.GetHandlers) and invoker must give zero, one or more EventHandlers which will be called by StaticEvent.

So, ViewModelBase class visits each its owners and combines all handlers found during this visit.

 

 

For example, Demo application realize this sequence on an example graph

image

Using the approach of the RoutedEvent model of WPF FrameworkElement solves …

  • Communicate between ViewModel instances
  • have good performance event with a huge quantity of entities

I will use this approach in a MVVM Framework to send message between ViewModel instances : Example : When an ViewModel entity will be validated, and if this ViewModel is owned by another : It would be very useful that the owner ViewModel instance can stop or not the validation process of its own Son ViewModel instances !

I use it for Filter event of my own ICollectionView instance, very useful in this case !

With this approach, each instance of ViewModel (that supports IHandlerRepository) keeps references of its own EventHandler. So even if you have 1 000 000 instances of ViewModel object and just ONE static event that uses by this instances : Each instance keep one and only one EventHandler ! and moreover, StaticEvent is not a strong reference (by EventHandler) on these 1 000 000 ViewModel objects :  of course : it does not know these objects !!

Prevent against Leak memory issues : Using Life event cycle of FrameworkElement

Each FrameworkElement have Loaded, Unloaded and Initialize event. If you look inside the Demo, ViewEvent class creates an adapter on each FrameworkElement target. This adapter supports IHandlerRepository interface. This adapter is memorized by FrameworkElement instance (with an attached dependency property) and It uses these 3 events for accept or not a call process !

NB : WPF RoutedEvent mechanism used a roughly same approach to memorize EventHandlers (see System.Windows.UncommonField<T> internal class in WindowBase.dll and System.Windows.UIElement.AddHandler method :-)

TODO List …

  • Invoke’s strategy like Bubble, Direct, Tunnel strategy of RoutedEvent.

Class diagrams

  • StaticEvent class hierarchy : StaticEvent<> is the most important class : It have a dependancy on IHandlersRepository
      • by ProvideHandlersRepository method
      • if a handler’s target implements or not this interface (in Add(EventHandler) calls)
      • if a sender implements or not this interface (in Invoke calls)

Framework

  • ViewModel entity class hierarchy : Just a demo to use StaticEvent in ViewModel part of MVVM architecture : ViewModelEvent allows to wired a FrameworkElement instance without leak memory errors. It uses Loaded/UnLoaded event of FrameworkElement

Framework.Window

Download

Download v2.20 03/29/2009

References

previous article : http://thibaud60.blogspot.com/2009/03/helper-to-create-weak-event-with-strong.html

samedi 14 mars 2009

Helper to create a weak event with strong typed signature

Introduction

When you create an event like this

public event EventHandler<MyEventArgs> MyEvent;

and you use it like this :

{
var receiver = new MyReceiverClass();
this.MyEvent += receiver.ReceiveMethod;

}

Receiver instance will be never cleaned in memory by Garbage Collector while “this” is referenced by any another object and, if "this" is Singleton object … receiver will be never free !!!! Even if receiver is not referenced somewhere … simply because it is referenced by the event of the Singleton :-(

.Net Framework provides us with some tools to avoid this problem. You can see e.g. this reference. It is the WeakEvent patterns.

This pattern works fine but it is a little hard and complex to create an object which receives an event with out strong reference : we need to implement IWeakEventListener interface or/and use a WeakEventManager.

My helper approaches the problem in a different way:

  • It is easy to use += / –= operator to wire/unwire event with exactly the same approach of that of a classical event
  • helper does not give a strong reference on receiver event
  • helper allows additionnal functions on FrameworkElement receivers:
    -> an unloaded instance will not received event!
    -> capacity to filter Execute calls when the event is wired on different receiver (not tested …)

Example of usage

To declare an event, you need just this code :

private UIWeakEventHandler<MyEventArgs> _myEvent;
public event EventHandler<MyEventArgs> MyEvent
{
add
{
_myEvent += value; // UIWeakEventHandler is created by += operator if necessary
}
remove
{
_myEvent –= value;
}
}

public void OnMyEvent(MyEventArgs e)
{
if (_myEvent != null)
_myEvent.Invoke(e);
}

and It”s All Folks :-)

MyEvent is a public event and supports classic += / –= operator so Visual Studio offers the traditionnal helper like auto-created-code when the developper press "+=" key sequence.

Why do I want to use this?

I need to create some events in my application on singleton instance and sometimes these events could be wired on WPF Window. When using a simple event, it is always necessary to wire on Loaded event of my Window and not forget to unwire event in Unloaded event of the same Window: when forgetting them will lead to some Leak memory error and it could take ages to find the origin of the problem. I hope this type of technical approach helps me!

Download

Download v2.10 (29/03/2009)

image

  • Complete refactoring ! I will create another post in fews days to explain all news functionnalities
    • IHandlersRepository interface : new name of IModelViewEventSupports

public interface IHandlersRepository
{
    void AddHandler(ModelRoutedEvent modelRoutedEvent, Delegate handler);
    void RemoveHandler(ModelRoutedEvent modelRoutedEvent, Delegate handler);
    void GetHandlers(ModelRoutedEvent modelRoutedEvent, object sender, EventArgs e, ref List<Delegate> result);
}

    • new RoutedPropertyChangedEvent and RoutedPropertyChangingEvent
    • Create FrameworkElementHandlersRepository class to optimize memory perfomance on FrameworkElement target (Same internal approach of RoutedEvent of .Net WPF framework)
    • Example with TreeView and Recursive ModelView entity
    • Include {MethodBinding} approach in TreeView Exampleimage

Download v1.20 

  • new interface IStorableEventsObject / IModelViewEventSupports to implements a “routed event pattern”  on ModelView object

Download v1.10

image

  • the main window can open secondary window via “New Windows” button
  • “Fire static event” calls a static event and changes a Label in secondary Windows
  • “Show counter” gives you the quantity of Window2 class instance
  • “GC.Collect” executes a memory collection >> Clic on “Show counter” to see the consequences of this collection

I never used this prototype in real application and so comments will be very welcomed :-)

Best regards

Class Diagram

WeakEventHandler

Todo list

  • I started to retro-analysis Routed event of WPF framework in order to understand the way is has been designed. For example, very good performances are certainly obtained by saving Event handler of a UIElement in the same UIElement (like Dependency proprerty mechanism): the static routed event instance is only an identifier of the event and does not memorises anything else.
    My own approach is different. I have a Weak-list of Event handler: when quantity of receiver instances is important (e.g. more than 10 000) >> will possibly result in having some performance problems during the invoking process.
    Routed approach will be possible only when invoker has a link with receiver. This link will be the Logical graph of user interface in "Routed Event and UIElement invoker". >> you can find a prototype of this approach in v1.20 version of download
  • I wish to interact between these static events and a graph of data object (ModelView part of Model - ModelView - View approach ) and when an instance of data object invokes a static event, My goal is that every ancestor (and only them) of this instance (in the graph) receives the event! >> you can find a prototype of this approach in v1.20 version of download

References