jeudi 9 juin 2016

IChangeTracking recursive AcceptChanges()

I have built a large model/system that uses INotifyPropertyChanged and IChangeTracking to track changes to any entity in the system:

public abstract class DependancyObject : INotifyPropertyChanged, IChangeTracking
{
    protected DependancyObject()
    {
        this.PropertyChanged += new PropertyChangedEventHandler(OnNotifiedOfPropertyChanged);
    }

    private void OnNotifiedOfPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e != null && !String.Equals(e.PropertyName, "IsChanged", StringComparison.Ordinal))
        {
            this.IsChanged = true;
        }
    }

    #region INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        OnPropertyChangedExplicit(propertyName);
    }

    protected void OnPropertyChanged<TProperty>(Expression<Func<TProperty>> projection)
    {
        var memberExpression = (MemberExpression)projection.Body;
        OnPropertyChangedExplicit(memberExpression.Member.Name);
    }

    void OnPropertyChangedExplicit(string propertyName)
    {
        //thread safe
        PropertyChangedEventHandler handler;
        lock (this)
        {
            handler = PropertyChanged;
        }

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    #endregion

    #region IChangeTracking

    public void AcceptChanges()
    {
        this.IsChanged = false;
    }

    public bool IsChanged
    {
        get
        {
            lock (_notifyingObjectIsChangedSyncRoot)
            {
                return _notifyingObjectIsChanged;
            }
        }

        protected set
        {
            lock (_notifyingObjectIsChangedSyncRoot)
            {
                if (!Boolean.Equals(_notifyingObjectIsChanged, value))
                {
                    _notifyingObjectIsChanged = value;

                    this.OnPropertyChanged("IsChanged");
                }
            }
        }
    }
    private bool _notifyingObjectIsChanged;
    private readonly object _notifyingObjectIsChangedSyncRoot = new Object();

    #endregion
}

This works very well. I have a lot of code that loops through object trees resetting the entity by calling AcceptChanges(). I was wandering whether someone has used reflection before to inspect each property of a type, and if it implements IChangeTracking or IEnumerable to call AcceptChanges recursively so it will navigate an instances entire tree.

private void BulkAcceptChanges(IEnumerable<IChangeTracking> items)
{
    foreach (var item in items)
    {
       item.AcceptChanges();

       //then inspect the item's properties for anything that implements IEnumerable<IChangeTracking> 
       //and call BulkAcceptChanges on that 
    }
}





Aucun commentaire:

Enregistrer un commentaire