0

I have the class which implements INotifyPropertyChanged and therefore I have the event:

public event PropertyChangedEventHandler PropertyChanged

There are a lot of places (more than 300) in the solution where event listeners subscribe to the PropertyChanged event using the standard operator +=. I want to change the way of subscription to using WeakEventManager to decrease the risks of memory leaks. And of course I wouldn't like to change all more than 300 places in the code. Here is what I was able to come up with but it doesn't work:

public event PropertyChangedEventHandler PropertyChanged
    {
        add
        {
            WeakEventManager<BaseNotifyPropertyChanged, EventArgs>.AddHandler(this, "PropertyChanged", (EventHandler<EventArgs>)value);
      //or
            PropertyChangedEventManager.AddHandler(this, value, "IsDirty");
        }
        remove
        {
           //....
        }
    }

But it is impossible to cast type PropertyChangedEventHandler to EventHandler<EventArgs>.

How can I resolve the problem?

UPD:

To resolve the issue above I used anonymous method:

WeakEventManager<BaseNotifyPropertyChanged, EventArgs>.AddHandler(this,
    "PropertyChanged",
    (sender, e) => value(sender, (PropertyChangedEventArgs)e));

Thanks PeterDuniho for advise.

But now if I try raise the event:

   protected virtual void RaiseOnPropertyChangedEvent(string propertyName)
{
    var handler = PropertyChanged;

    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(propertyName));
   }
}

I got the next error: The event PropertyChanged can only appear on the left hand side of += or -=

This error is quite known, but in another context. What is the reason?

1 Answers1

1

Unfortunately, delegate variance doesn't address this scenario. But you can usually use an anonymous method to adapt one delegate type to another, using casting within the anonymous method to get the code to compile. For example:

WeakEventManager<BaseNotifyPropertyChanged, EventArgs>.AddHandler(this,
    "PropertyChanged",
    (sender, e) => value(sender, (PropertyChangedEventArgs)e));

I.e. provide a handler that accepts the EventArgs object allowed by your WeakEventManager declaration, and then downcast the object passed to that anonymous method handler so that it can then be passed to the actual handler that requires ProgressChangedEventArgs.

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • Thank you Peter for really good advice. But I have faced with another problem, I've just updated the question. – Maksim Nikitin Nov 20 '15 at 08:31
  • Without a complete code example, it's impossible to say. But I would guess that you are trying to raise the event by name, from a derived class rather than the class where the event is declared. That's not allowed. See e.g. http://stackoverflow.com/questions/756237/c-raising-an-inherited-event for the correct way to accomplish that. – Peter Duniho Nov 20 '15 at 08:38