Свойство дескриптора изменяет слушателей события (многие из них) более изящно (словарь?)

ПРИВЕТ!

Здесь у меня есть простой пример класса с тремя полями класса B типа и некоторого другого материала. Поскольку Вы видите, что я слушаю на каждом изменении дочернего объекта. Так как мне могло быть нужно много свойств класса B типа, я задаюсь вопросом, существует ли способ уменьшить код. При создании слушателя + метод для каждого кажется, что у меня будет МНОГО кода. Как я зафиксировал бы это... использование словаря или чего-то подобного? Мне сказали, что МОК мог зафиксировать это, но я не уверен, где запустить.

public class A : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public int _id;
    public int Id
    {
        get { return _id; }
        set
        {
            if (_id == value)
            {
                return;
            }

            _id = value;
            OnPropertyChanged("Id"); 
        }
    }

    public string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            if (_name == value)
            {
                return;
            }

            _name = value; 
            OnPropertyChanged("Name"); 
        }
    }

    public B _firstB;
    public B FirstB
    {
        get { return _firstB; }
        set 
        {
            if (_firstB == value)
            {
                return;
            }

            if (_firstB != null)
            {
                FirstB.PropertyChanged -= firstObjectB_Listener;
            }

            _firstB = value;

            if (_firstB != null) 
                FirstB.PropertyChanged += new PropertyChangedEventHandler(firstObjectB_Listener);

            OnPropertyChanged("FirstB"); 
        }
    }

    public B _secondB;
    public B SecondB
    {
        get { return _secondB; }
        set
        {
            if (_secondB == value)
            {
                return;
            }

            if (_secondB != null)
            {
                FirstB.PropertyChanged -= secondObjectB_Listener;
            }

            _secondB = value;

            if (_secondB != null)
                SecondB.PropertyChanged += new PropertyChangedEventHandler(secondObjectB_Listener);

            OnPropertyChanged("FirstB");
        }
    }

    public B _thirdB;
    public B ThirdB
    {
        get { return _thirdB; }
        set
        {
            if (_thirdB == value)
            {
                return;
            }

            if (_thirdB != null)
            {
                ThirdB.PropertyChanged -= thirdObjectB_Listener;
            }

            _thirdB = value;

            if (_thirdB != null)
                ThirdB.PropertyChanged += new PropertyChangedEventHandler(thirdObjectB_Listener);

            OnPropertyChanged("ThirdB");
        }
    }

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }

    void firstObjectB_Listener(object sender, PropertyChangedEventArgs e)
    {
        Console.WriteLine("Object A has found a change of " + e.PropertyName + " on first object B");
    }

    void secondObjectB_Listener(object sender, PropertyChangedEventArgs e)
    {
        Console.WriteLine("Object A has found a change of " + e.PropertyName + " on second object B");
    }

    void thirdObjectB_Listener(object sender, PropertyChangedEventArgs e)
    {
        Console.WriteLine("Object A has found a change of " + e.PropertyName + " on third object B");
    }
}
5
задан no9 16 March 2010 в 11:05
поделиться

3 ответа

Самый элегантный способ, который я знаю, - это использовать аспектно-ориентированное программирование (АОП) с таким инструментом, как PostSharp . Я нашел примеры реализации INotifyPropertyChanged здесь и здесь . Это позволяет вам украсить ваши свойства атрибутом, а PostSharp затем реализует INotifyPropertyChanged для вас при построении кода.

2
ответ дан 15 December 2019 в 06:22
поделиться

Чтобы немного упростить, вы можете сделать следующие две вещи.

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

private void BValueListener(object sender, PropertyChangedEventArgs e)
{
  Console.WriteLine("Found change of {0} on object {1}", e.PropertyName, sender);
}

Если вам нужно точно знать, какое из свойств B было отправлено, вы можете проверить его в методе BValueListener.

if (sender == FirstB) { /* Do special stuff here */ }

Имея один и тот же слушатель для всех свойств B, мы можем перейти к написанию установщика свойств, например:

private B _thirdB;
public B ThirdB
{
  get { return _thirdB; }
  set {
    if (UpdateBValue(ref _thirdB, value)) {
      OnPropertyChanged("ThirdB");
    }
  }
}
private bool UpdateBValue(ref B value, B newValue)
{
  if (value == newValue)
  {
    return false;
  }

  if (value != null)
  {
    value.PropertyChanged -= BValueListener;
  }

  value = newValue;
  if (value != null)
  {
    value.PropertyChanged += BValueListener;
  }
  return true;
}

Если вам действительно нужны разные обработчики для каждого свойства, вы можете изменить приведенный выше код на что-то вроде

private B _thirdB;
public B ThirdB
{
    get { return _thirdB; }
    set 
    { 
        if (UpdateBValue(ref _thirdB, value, BValueListener))
        {
            OnPropertyChanged("ThirdB");
        }
    }
} 

private bool UpdateBValue(ref B value, B newValue, PropertyChangedEventHandler eventHandler)
{
    if (value == newValue)
    {
        return false;
    }

    if (value != null)
    {
        value.PropertyChanged -= eventHandler;
    }

    value = newValue;

    if (value != null)
    {
        value.PropertyChanged += eventHandler;
    }
    return true;
}

, где вы может отправить метод прослушивателя, который вы хотели бы использовать в каждом случае.

0
ответ дан 15 December 2019 в 06:22
поделиться

Один хороший способ упростить настройку свойств можно найти здесь .

Что касается ваших каскадных уведомлений: я предполагаю, что вы могли бы использовать описанный выше подход для обработки (отмены) подписки на события для свойств, реализующих там INotifyPropertyChanged .

0
ответ дан 15 December 2019 в 06:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: