1

I have a simple POCO with a lot of Properties. To simplify things let´s assume the POCO looks like this:

public class Project
{
    public int ProjectId {get; set;}
}

Now I want to create an Event that fires when the ProjectId is changed. What I have now is this:

public class Project
{
    public int ProjectId {get; set;}

    public event EventHandler ProjectChanged;

    private void OnProjectChanged(EventArgs args)
    {
        if (ProjectChanged != null) ProjectChanged (this, args);
    }
}

Now I have to extend the Property in order to call the Eventhandler:

public class Project
{
    private int mProjectId;
    public int ProjectId
    {
        get { return this.mProjectId;}
        set
        {
            this.mProjectId = value;
            this.OnProjectChanged(EventArgs.Empty);
        }
    }

    public event EventHandler ProjectChanged;

    private void OnProjectChanged(EventArgs args)
    {
        if (ProjectChanged != null) ProjectChanged(this, args);
    }
}

I wonder if there is an easier way to attach the Eventhandler. Maybe some kind of annotation ? Like

public class Project
{
    [OnChange("OnProjectChanged", EventArgs.Empty)]
    public int ProjectId {get; set;}

    public event EventHandler ProjectChanged;

    private void OnProjectChanged(EventArgs args)
    {
        if (ProjectChanged != null) ProjectChanged (this, args);
    }
}
tafkab76
  • 465
  • 1
  • 6
  • 18
  • 2
    Have a look at this question which is doing something similar with the in-built `INotifyPropertyChanged` interface: http://stackoverflow.com/questions/1315621/implementing-inotifypropertychanged-does-a-better-way-exist – CodingIntrigue Jan 24 '14 at 08:23

1 Answers1

1

Taking some ideas from the question I posted in the comments, you could implement an abstract base class which implements INotifyPropertyChanged. Each time you declare a property, you call SetField to trigger the PropertyChanged event.

This avoids two things:

1) Explicitly implementing INotifyProperty changed each time using the abstract class

2) Explicitly implementing a method to trigger the event each time, shortening the set code to one line.

abstract class ModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
    protected bool SetField<T>(ref T field, T value, string propertyName)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }
}

class Project : ModelBase
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set { SetField(ref _name, value, "Name"); }
    }
}

class TestRunner
{
    public TestRunner()
    {
        Project p = new Project();
        p.PropertyChanged += (o, e) =>
        {
            // Changed
        };
        p.Name = "Test";
    }
}
CodingIntrigue
  • 75,930
  • 30
  • 170
  • 176
  • That looks really interesting. Though not really less effort it is more elegant for sure. Is there a reason why you (and the original author) use `PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));` instead of just `if(PropertyChanged != null) PropertyChanged(propertyName));`? – tafkab76 Jan 24 '14 at 08:36
  • 1
    @tafkab76 To ensure thread safety. If you check `PropertyChanged` first and another thread removes their handler, you could end up accessing a null reference – CodingIntrigue Jan 24 '14 at 08:39
  • Hmmm...I´m still not getting this. So if I succesfully check PropertyChanged is not null, then another thread moves his handler from the PropertyChanged-Event I get a null reference exception. Seems legit. But how can assigning PropertyChanged to a local variable prevent that behaviour? Isn´t `handler` just a reference to `PropertyChanged`? – tafkab76 Jan 24 '14 at 08:48
  • 1
    Normally, but Delegates are immutable so assigning it to a variable is really taking a snapshot of that delegate. More information from someone much more intelligent than me here: http://stackoverflow.com/questions/2598170/question-regarding-to-value-reference-type-of-events - Another option would be to simply add a `lock` – CodingIntrigue Jan 24 '14 at 09:54