Weak Events

by Florin 16. February 2010 12:06

 

Pentru a intelege ce sunt WeakEvents trebuie intai clarificat cum functioneaza evenimentele in .NET. Codul standard prin care se adauga un handler la un eveniment este:

eveniment += OnEvent;

unde OnEvent este o metoda din aceeasi clasa, care declara un parametru sender si un eventArgs. Deinregistrarea evenimentului se face astfel:

eveniment -= OnEvent;

Ar parea ca un eveniment este o colectie de delegates care este apelata la declansarea evenimentului, dar atentie, aceasta colectie este incapsulta intr-o proprietate. Astfel .NET Framework introduce constrangeri la accesul din exterior:

  • Un eveniment nu poate fi lansat decat dintr-o metoda ce apartine clasei care defineste evenimentul.
  • O clasa externa nu poate itera si accesa handlere ale evenimentului care sunt adaugate din alte clase.
  • O clasa externa nu poate sterge lista de handlere ale evenimentului.
  • O clasa poate doar sa-si deinregistreze propriile handlere.

Ideea din spatele acestei incapsulari este separabilitatea si decuplarea componentelor intr-o aplicatie. Evenimentele introduc doar weak-coupling in arhitectura, pentru ca nu avem dependinte intre clasele ce trateaza aceeasi eveniment. Daca clasele ar avea acces la handlerele definite in alte clase (de exemplu prin stergerea listei), interdependintele dintre module ar fi foarte complicat de urmarit.

Totusi pe langa avantejele oferite de incapsulare, exista un dezavantaj important al faptului ca evenimentele mentin lista de handlere sub forma unei proprietati. Cat timp exista handlere pentru un eveniment adaugate din exterior, obiectul respectiv nu poate fi eliberat de Garbage Collector. Acest lucru se intampla chiar daca evenimentul respectiv nu se va mai apela niciodata. Codul exterior in schimb nu are de unde sa stie acest lucru. Acesta este un caz clasic de memory leak.

 

WPF Weak Events

Pentru a rezolva aceasta problema, in WPF se pot folosi evenimete slabe.

Pentru a creea evenimente slabe, trebuie sa suprascriem definitia evenimentului nostru si sa declaram explicit codul din accesorii add si remove. Sa prespunem ca in cadrul unei clase, vrem sa definim un eveniment slab numit Click.

private WeakDelegateSet clickDelegateList = new WeakDelegateSet(); 
public event EventHandler CustomClick
    add { clickDelegateList.Add(value); } 
    remove { clickDelegateList .Remove(value); } 
}

Pentru a creea evenimente slabe, trebuie sa suprascriem definitia evenimentului nostru si sa declaram explicit codul din accesorii add si remove. Se poate vedea ca in exemplul dat, ne declaram noi lista de delegati care vor fi apelati.

Pentru a declansa evenimentul din interiorul obiectului nu apelam MyWeakEvent.Invoke() ci apelam metoda Invoke a setului de delegates, astfel:

clickDelegateList.Invoke(this, EventArgs.Empty);

Aceasta este ceea mai facila metoda prin care se pot implementa evenimente slabe in WPF. O metoda alternativa este ceea descrisa de Microsoft in articolul WeakEvent Patterns:

http://msdn.microsoft.com/en-us/library/aa970850.aspx

Dezavantajul acestei metode este ca trebuie implementat cate un WeakEventManager pentru fiecare tip de eveniment slab care vrem sa il folosim. Fiecare listener de evenimente trebuie de asemenea sa implementeze interfata IWeakEventListener. Pentru ca handlerele sunt tinute separat de obiectele care genereaza evenimentele (sunt tinute in manager), nu apar probleme de memory leaks.

 

Tags:

Comments

Add comment

Nume

Email

Website

biuquote
Loading



Powered by BlogEngine.NET 1.5.0.7