如何使用具有属性更改跟踪的对象处理初始化

时间:2014-02-05 19:35:20

标签: c# change-tracking

感谢Marc Gravell的精彩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目前被用作aspx页面上的proprety,我将对象存储在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; }
}

2 个答案:

答案 0 :(得分:5)

这是创建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();

编辑:您可能也会考虑实施INotifyPropertyChanged,因为您已经完成了大部分工作。

答案 1 :(得分:0)

我有一次非常类似的问题。使用ctor的想法对我不起作用,因为该对象是通过XML反序列化创建和初始化的。

我使用的相当丑陋的解决方案是伪全局初始化bool变量(线程静态变量,http://msdn.microsoft.com/library/system.threadstaticattribute%28v=vs.110%29.aspx)。在反序列化数据之前,我将bool设置为true,并在反序列化完成后将其重置为false(使用try-finally结构是安全的)。在我的PropertyChanged处理程序中,我检查了那个bool。如果这是真的,我只是没有解雇我的事件。

这是一个非常难看的解决方案。我甚至不喜欢将它称为解决方案,因为每次调用PropertyChanged处理程序时都会检查该bool变量。它不是一种干净或保存方法,因为您必须确保在初始化期间仅设置该bool,并且必须确保之后重置它。但它对我有用。