INotifyPropertyChanged подписавшись на себя - PullRequest
2 голосов
/ 13 апреля 2011

У меня есть класс, который реализует INotifyPropertyChanged.Я использую превосходный NotifyPropertyWeaver Саймона Кроппа для ввода кода INotifyPropertyChanged в свойства.Однако теперь мне нужно изменить сеттеры для набора свойств, чтобы все делали то же самое после завершения набора.Модификация сеттеров требует создания вспомогательных полей, реализации get, реализации set и т. Д. С идентичными реализациями, кроме имени поддерживающего поля.Я просто избегал делать все это, используя NotifyPropertyWeaver .

Вместо этого я мог бы заставить мой класс подписаться на собственное событие PropertyChanged и обработать операцию пост-изменения в обработчике события.Это безопасная вещь?Я понимаю, что мне придется следить за бесконечной рекурсией, приводящей к переполнению стека, если моя операция изменяет одно из свойств, которые я наблюдаю.Есть ли еще какие-то проблемы, за которыми мне нужно следить?

Вот пример

public class Foo : INotifyPropertyChanged{
    public event PropertyChangedEventHandler PropertyChanged;

    public Prop1 { get; set; }
    public Prop2 { get; set; }
    public Prop3 { get; set; }
    public Prop4 { get; set; }

    public Foo(){
        this.PropertyChanged +=
            new PropertyChangedEventHandler(Foo_PropertyChanged);
    }

    private void Foo_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        switch (e.PropertyName)
        {
            case "Prop1":
            case "Prop2":
            case "Prop3":
                DoSomething();
                break;
            case "Prop4":
                DoSomethingElse();
                break;
        }
    }

    private void DoSomething()
    {
        ....
    }

    private void DoSomethingElse()
    {
        ....
    }
}

Редактировать

Джоэл Люси любезно указал, что мне не нужно подписываться на событие.Я позволял NotifyPropertyWeaver вводить OnPropertyChanged.Вместо этого я мог просто реализовать OnPropertyChanged, чтобы выполнить то же самое.

Обновленный код:

public class Foo : INotifyPropertyChanged{
    public event PropertyChangedEventHandler PropertyChanged;

    public Prop1 { get; set; }
    public Prop2 { get; set; }
    public Prop3 { get; set; }
    public Prop4 { get; set; }

    private void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
        switch (propertyName)
        {
            case "Prop1":
            case "Prop2":
            case "Prop3":
                DoSomething();
                break;
            case "Prop4":
                DoSomethingElse();
                break;
        }
    }

    private void DoSomething()
    {
        ....
    }

    private void DoSomethingElse()
    {
        ....
    }
}

Ответы [ 3 ]

1 голос
/ 13 апреля 2011

С одной стороны, вы просто реализуете OnPropertyChanged и не должны использовать событие.

Во-вторых, это считается дурным тоном. NotifyPropertyWeaver выполняет много проверок в коде и обнаруживает зависимости между свойствами. Например, если вы используете свойство A внутри кода для свойства B, NotifyPropertyWeaver добавит второй OnPropertyChanged для B внутри кода для A, чтобы убедиться, что все обновлено.

Короче, не делай так, набери все.

0 голосов
/ 26 сентября 2011

Я добавил функцию On_PropertyName_Changed в NotifyPropertyWeaver http://code.google.com/p/notifypropertyweaver/wiki/On_PropertyName_Changed

Так что, если вы напишите это

public class Foo : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
    public string Prop3 { get; set; }
    public string Prop4 { get; set; }

    void OnProp3Changed()
    {
    }

    void OnProp4Changed()
    {
    }
}

Вызовы OnProp3Changed и OnProp4Changed будут внедрены в наборы Prop3 и Prop4 соответственно.

0 голосов
/ 13 апреля 2011

Я сделал этот / используемый код, который делал это раньше, и не заметил больших побочных эффектов в коде. В зависимости от количества свойств вы можете увидеть снижение производительности, но, вероятно, оно будет незначительным. Что я заметил, так это то, что не всегда сразу понятно при взгляде на код, почему происходят эффекты, когда вы используете этот шаблон. Что вы должны быть осторожны, так это то, как вы проектируете свои классы. Автоматические свойства хороши, когда вы собираете класс быстро, но они могут стать помехой для всего вашего дизайна. Я обычно не использую их, если это не быстрый макет объекта или очень простой объект, который я использую для передачи данных. Вопрос, который вы должны задать себе, заключается в том, проектируете ли вы свой объект таким образом, потому что он лучше всего подходит для вашего кода, программы, стиля или потому что вы пытаетесь использовать определенную функцию, то есть автоматические свойства.

Одна вещь, на которую стоит обратить внимание, это то, собираетесь ли вы выполнять одно и то же действие для каждого поля, или у вас будут разные действия? Если у вас разные действия, вы быстро получаете громоздкий метод. Если это одни и те же действия, им, вероятно, легче управлять.

Обычный способ реализации интерфейса INotifyProperty состоит в создании метода, который изменяет поле, выполняет уведомление, а также может выполнить Action для выполнения после внесения изменения. Это позволяет избежать всех больших условных операторов и дает точный контроль зерна над действиями, но имеет достаточно точный контроль зерна, чтобы быть полностью гибким. Если я создаю много связанных между собой объектов, я обычно просто создаю базовый класс для наследования всех из них, у которого есть этот метод изменения как защищенный метод, поэтому мне не нужно повторно реализовывать шаблон один раз за класс.

...