Получить измененные свойства в том же объекте

#c#

#c#

Вопрос:

У меня есть объект с пятью свойствами, и каждое из этих свойств имеет два состояния («до» и «после»).

Как мне получить информацию о том, какие свойства изменили свое состояние?

Единственный способ, с которым я знаком, — это получить список всех свойств (используя отражение?), Затем использовать цикл для сравнения каждого свойства между двумя объектами и сохранения информации о тех, которые были изменены.

Есть ли простой способ сделать это, возможно, используя LINQ?

Комментарии:

1. Интерфейс INotifyPropertyChanged

2. @EZI-Я уже читал об этом, но не понял, как это может мне помочь, поскольку как я могу получить только то свойство, которое было изменено, например, если были изменены только f2 и f3…

3. @M.Herbert Не уверен, почему вы отметили этот LINQ

Ответ №1:

Интерфейс INotifyProprtyChanged требует от вас реализации события PropertyChanged . Вы можете подписаться на этот интерфейс в самом классе и отслеживать свойства, для которых они вызываются.

Например:

 internal class SampleClass : INotifyPropertyChanged{
    public event PropertyChangedEventHandler PropertyChanged;
    private string _SampleProperty;
    internal List<string> _ChangedProperties;

    public SampleClass() {
      this.PropertyChanged  = SampleClass_PropertyChanged;
      _ChangedProperties = new List<string>();
    }

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

    void SampleClass_PropertyChanged( object sender, PropertyChangedEventArgs e ) {
      if ( _ChangedProperties.Contains( e.PropertyName ) ) return;
      _ChangedProperties.Add( e.PropertyName );
    }

    public string SampleProperty {
      get { return _SampleProperty; }
      set {
        if (_SampleProperty == value )
          return;
        _SampleProperty = value;
        OnPropertyChanged( "SampleProperty" );
      }
    }
}
  

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

Я не учитывал потокобезопасность, я бы не считал этот образец готовым к производству.

Комментарии:

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

2. @Groo Конечно, еще одна причина, по которой я упомянул этот пример, не является производственным кодом. Обновит мой вопрос, хотя

3. @Sascha-спасибо проголосовавшим, я обязательно попробую это, мой вопрос в том, предположим, у меня есть поля F1-F10, нужно ли мне делать это для всех полей (что вы сделали для свойства sample? или есть более короткий способ сделать это? 2. Предположим, что у меня есть Obj1 и object2 из одного класса, это лучший способ найти свойства, которые были изменены?

4. Вы также можете выполнить: void OnPropertyChanged([CallerMemberName] string propertyName = "") , а затем вызвать: OnPropertyChanged() напрямую. Проверьте это: msdn.microsoft.com/en-us/library /… для получения более подробной информации:D

5. @M.Herbert Вам необходимо поддерживать INotifyPropertyChanged механизмы для всех полей. Каждый класс содержит измененные поля для себя, если вы хотите сопоставить их с другим объектом, чем вам нужно для сравнения

Ответ №2:

Вы можете сделать что-то вроде этого:

 public delegate void PropertyChangedEventHandler(object sender, PropertyChangedEventArgs e);
public class PropertyChangedEventArgs : EventArgs
{
    public PropertyChangedEventArgs(string propertyName, dynamic oldValue, dynamic newValue)
    {
        this.PropertyName = propertyName;
        this.OldValue = oldValue;
        this.NewValue = newValue;
    }

    public virtual string PropertyName { get; private set; }
    public virtual dynamic OldValue { get; private set; }
    public virtual dynamic NewValue { get; private set; }
}

public class PropertyClass
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void Set<T>(string propertyName, ref T field, T value)
    {
        if (field.Equals(value))
            return;

        T oldValue = value;
        field = value;

        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName, oldValue, value));
    }

    // Properties
    private string _name;
    private string _message;
    private bool _isMember;

    public string Name
    {
        get { return _name; }
        set { Set("Name", ref _name, value); }
    }

    public string Message
    {
        get { return _message; }
        set { Set("Message", ref _message, value); }
    }

    public bool IsMember
    {
        get { return _isMember; }
        set { Set("IsMember", ref _isMember, value); }
    }
}