#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 /… для получения более подробной информации:D5. @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); }
}
}