2014-02-05 4 views
0

Благодаря замечательному Marc Gravell's answer мне удалось реализовать отслеживание изменений свойств в моем классе. Однако, когда объект сначала инициализируется, и свойства, заданные в первый раз, все свойства помечены как грязные. Каким будет лучший способ обработки первоначальной настройки свойств, чтобы они не были загрязнены при первой загрузке объекта?Как обрабатывать инициализацию с объектом, у которого есть отслеживание изменения свойств

Поэтому, когда ExtendedFieldDto свойства заданы первым dirtyProperties всегда имеет счет, равный свойствам наследующего класса, в данном случае ExtendedFieldDto.

public abstract class NotifyPropertyChanged { 
    public IDictionary<string, object> dirtyProperties { get; private set; } 

    protected NotifyPropertyChanged() { 
     dirtyProperties = new Dictionary<string, object>(); 
    } 

    protected void setProperty<T>(ref T property, T value, string propertyName) { 
     if (!EqualityComparer<T>.Default.Equals(property, value)) { 
      property = value; 
      if (dirtyProperties.Keys.Contains(propertyName)) 
       dirtyProperties[propertyName] = property; 
      else 
       dirtyProperties.Add(propertyName, property); 
     } 
    } 
} 

public class ExtendedFieldDto : NotifyPropertyChanged { 
    private string _id; 
    public string id { 
     get { return _id; } 
     set { setProperty(ref _id, value, "id"); } 
    } 

    private int _idLocation; 
    public int idLocation { 
     get { return _idLocation; } 
     set { setProperty(ref _idLocation, value, "idLocation"); } 
    } 

    private string _columnName; 
    public string columnName { 
     get { return _columnName; } 
     set { setProperty(ref _columnName, value, "columnName"); } 
    } 

    private string _description; 
    public string description { 
     get { return _description; } 
     set { setProperty(ref _description, value, "description"); } 
    } 

    private string _help; 
    public string help { 
     get { return _help; } 
     set { setProperty(ref _help, value, "help"); } 
    } 
} 

DTO в настоящее время используется в качестве proprety на-страницы ASPX, где я хранящий объект в ViewState (требование от унаследованного кода). Поэтому я не уверен, как использовать конструктор для ExtendedFieldDto, чтобы установить частные свойства с этим типом реализации.

private ExtendedFieldDto extendedField { 
    get { 
     if (ViewState[EXTENDED_FIELD_VIEWSTATE_KEY] == null) 
      ViewState[EXTENDED_FIELD_VIEWSTATE_KEY] = new ExtendedFieldDto(); 
     return (ExtendedFieldDto)ViewState[EXTENDED_FIELD_VIEWSTATE_KEY]; 
    } 
    set { ViewState[EXTENDED_FIELD_VIEWSTATE_KEY] = value; } 
} 
+0

Не могли бы вы использовать конструктор, который устанавливает ваши личные поля? Это не должно вызывать setProperty. – Vlad

+0

@ Vlad Да, что бы def работать, но реальный объект имеет более 20 свойств и делает управление объектом (то есть: добавление/удаление свойств) видом боли. Это может быть лучшим способом:/ – bflemi3

+0

@ Vlad Кроме того, с моей текущей реализацией я сохраняю этот объект в ViewState, поэтому у меня есть свойство для объекта в моем aspx, которое на геттере инициализирует объект, если ViewState KeyValue Pair не существует. Поэтому не уверен, как я буду передавать все свойства там. 'get {if (ViewState [EXTENDED_FIELD_VIEWSTATE_KEY] == null) ViewState [EXTENDED_FIELD_VIEWSTATE_KEY] = new ExtendedFieldDto(); return (ExtendedFieldDto) ViewState [EXTENDED_FIELD_VIEWSTATE_KEY]; } ' – bflemi3

ответ

4

Это одна из многих распространенных проблем, для которой был создан интерфейс ISupportInitialize.

public abstract class NotifyPropertyChanged : ISupportInitialize { 
    ... 
    public void BeginInit() { } 
    public void EndInit() { PropertyChangedObserver(); } 
} 

и использовать его как это:

ExtendedFieldDto foo = new ExtendedFieldDto(); 
foo.BeginInit(); 
foo.id = "abc123"; 
foo.idLocation = 0; 
... 
foo.EndInit(); 

EDIT: Вы могли бы также подумать о реализации INotifyPropertyChanged в то время как вы на него, так как вы уже большую часть пути туда.

+0

Отличный интерфейс: ISupportInitialize. Я не знал этого. К сожалению, XmlSerializer.Deserialize (.Net v4.0), похоже, не использует его. – Knowleech

0

У меня была очень похожая проблема один раз. Идея использования ctor не работала для меня, потому что объект был создан и инициализирован десериализацией XML.

Скорее уродливое решение, которое я использовал, было псевдоглобальной инициализирующей переменной bool (thread-static variable, http://msdn.microsoft.com/library/system.threadstaticattribute%28v=vs.110%29.aspx). Перед десериализацией данных я установил, что bool в true и после завершения десериализации я верну его в false (используя конструкцию try-finally, которая будет безопасной). В обработчиках PropertyChanged я проверил, что bool. Если это правда, я просто не возбуждал свои события.

Это очень уродливое решение. Мне даже не нравится называть это решением вообще, из-за проверки этой переменной bool каждый раз, когда вызывается обработчик PropertyChanged. Это не чистый или безопасный подход, так как вы обязательно должны установить этот bool во время инициализации, и вы обязательно должны его сбросить позже. Но это сработало для меня.

+0

Я тоже об этом думал, но мне не нравилась идея, что клиент должен беспокоиться о чем-либо, кроме установки объекта. – bflemi3

+0

Возможно, это может быть изменено так, чтобы свойства имели некоторые неясные начальные значения, а setproperty не запускается, если значение меняет «от» начального значения. Хотя это, вероятно, будет выглядеть довольно странно, и я не уверен, какие исходные значения могут/должны быть. – Vlad

 Смежные вопросы

  • Нет связанных вопросов^_^