There is a class that implements INotifyPropertyChanged, therefore, there is an event in the class

public event PropertyChangedEventHandler PropertyChanged 

A subscription to this event occurs in more than 300 places with a simple + operator. The goal is to use WeakEventManager to avoid memory leaks. Of course, I don’t want to change the way I subscribe to in 300 places, the poet wants to get out somehow. All I could come up with (but it does not work):

 public event PropertyChangedEventHandler PropertyChanged { add { WeakEventManager<BaseNotifyPropertyChanged, EventArgs>.AddHandler(this, "PropertyChanged", (EventHandler<EventArgs>)value); //либо же PropertyChangedEventManager.AddHandler(this, value, "IsDirty"); } remove { //аналогичный код } } 

And in the case of WeakEventManager, and PropertyChangedEventManager, the compiler curses the impossibility of casting PropertyChangedEventHandler to EventHandler. Is there any way to solve the problem?

UPD:

I solved the problems above in this way:

  public event PropertyChangedEventHandler PropertyChanged { add { WeakEventManager<BaseNotifyPropertyChanged, EventArgs>.AddHandler(this, "PropertyChanged", (sender, e) => value(sender, (PropertyChangedEventArgs)e)); } remove { WeakEventManager<BaseNotifyPropertyChanged, EventArgs>.RemoveHandler(this, "PropertyChanged", (sender, e) => value(sender, (PropertyChangedEventArgs)e)); } } 

But now in this code

  protected virtual void RaiseOnPropertyChangedEvent(string propertyName) { var handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } 

The compiler swears: The event Property can be seen only on the left hand side of + = or - =

The error text is quite common, but it appears in other people in a different context.

  • Well, “the impossibility of casting PropertyChangedEventHandler to EventHandler” is just understandable, but why are you doing a cast by force? Why not use the right type? - VladD
  • You are right, I updated the question. - MaksimNikicin
  • Ok, I could get the code to compile . But I’m not sure if it’s right , you need to experiment and read the documentation. - VladD
  • It kompilitsya, but will fall in rantayme since WeakEventManager will not see a private event PropertyChangedInternal - MaksimNikicin
  • Well, this event can be made public for a while to see if this solves the problem. - VladD 4:41

1 answer 1

In the Source class there is a Notify event, you can connect a handler to it as usual. But at the same time, weak references to subscribers are used in the Notify implementation. If there are no other links to Target, then there is no link to Target in Source.

 using System.Collections.Concurrent; static void Main(string[] args) { var s = Start(); s.Run(); // будет вызван t.Handler var arr = new int[100000000]; Console.WriteLine("APP: arr[{0}]", arr.Length); s.Run(); // t.Handler больше не вызывается Console.WriteLine("APP: done"); } static Source Start() { var s = new Source(); var t = new Target(); s.Notify += t.Handler; return s; } class Target { int[] arr = new int[10000000]; public void Handler(object sender, EventArgs e) { Console.WriteLine("TARGET: notified"); } } class Source { List<WeakReference<EventHandler>> _Handlers; public Source() { _Handlers = new List<WeakReference<EventHandler>>(); } public event EventHandler Notify { add { _Handlers.Add(new WeakReference<EventHandler>(value)); } remove { Console.WriteLine("SOURCE: remove"); /* todo */ } } public void Run() { foreach (var w in _Handlers) { EventHandler h; if (w.TryGetTarget(out h)) h.Invoke(this, EventArgs.Empty); } } } 

If necessary, it is necessary to periodically clear _Handlers from WeakReference with 'broken' links.