Exemple #1
0
        public IEnumerable<Model> RemoveBranch (Model model)
        {
            Node node;
            if (!nodes.TryGetValue (model, out node))
                return Enumerable.Empty<Model> ();

            var removedModels = new List<Model> ();

            // Find elders (highest parents):
            var elders = new HashSet<Model> ();
            var parentStack = new Stack<Model> ();
            parentStack.Push (model);
            while (parentStack.Count > 0) {
                var parent = parentStack.Pop ();

                var parentNode = nodes [parent];
                if (parentNode.Parents.Count == 0) {
                    elders.Add (parent);
                } else {
                    foreach (var grandparent in parentNode.Parents) {
                        parentStack.Push (grandparent);
                    }
                }
            }

            // Remove elders from graph:
            foreach (var elder in elders) {
                Remove (elder, removedModels);
            }

            return removedModels;
        }
Exemple #2
0
        public virtual void Merge (Model model)
        {
            if (model.GetType () != GetType ())
                throw new ArgumentException ("Cannot merge models of different kind", "model");

            lock (SyncRoot) {
                MergeSimpleOverwrite (model);
            }
        }
Exemple #3
0
        public IEnumerable<Model> Remove (Model model)
        {
            Node node;
            if (!nodes.TryGetValue (model, out node))
                return Enumerable.Empty<Model> ();

            var removedModels = new List<Model> ();
            Remove (model, removedModels);
            return removedModels;
        }
Exemple #4
0
        public void Add (Model model, Model parent = null)
        {
            if (parent != null)
                Add (parent);

            Node node;
            if (!nodes.TryGetValue (model, out node)) {
                nodes [model] = node = new Node ();
            }

            if (parent != null) {
                node.Parents.Add (parent);
                nodes [parent].Children.Add (model);
            }
        }
Exemple #5
0
        private void Remove (Model model, List<Model> deleted)
        {
            Node node;
            if (!nodes.TryGetValue (model, out node))
                return;

            // Remove children
            foreach (var child in node.Children.ToList ()) {
                Remove (child, deleted);
            }

            // Detach from parents
            foreach (var parent in node.Parents.ToList ()) {
                nodes [parent].Children.Remove (model);
            }

            nodes.Remove (model);
            deleted.Add (model);
        }
Exemple #6
0
        protected void MergeSimpleOverwrite (Model other)
        {
            if (this.IsShared && other.IsShared)
                throw new InvalidOperationException ("Cannot merge two shared models.");

            IsMerging = true;
            try {
                // Very simple merging rules: the newest one is always correct, remote deletion overrides everything.
                if (other.ModifiedAt <= this.ModifiedAt && other.RemoteDeletedAt == null)
                    return;

                // Update properties defined in subclasses:
                var props =
                    from p in GetType ().GetProperties ()
                                   where p.CanRead && p.CanWrite && p.DeclaringType != typeof(Model)
                                   select p;

                foreach (var prop in props) {
                    var val = prop.GetValue (other, null);
                    prop.SetValue (this, val, null);
                }

                // Update our own properties in a specific order:
                this.RemoteId = other.RemoteId;
                this.RemoteDeletedAt = other.RemoteDeletedAt;
                this.RemoteRejected = other.RemoteRejected;
                if (other.RemoteDeletedAt != null) {
                    // Custom logic for handling remote deletions:
                    this.IsPersisted = false;
                    this.DeletedAt = other.RemoteDeletedAt.Value;
                } else {
                    if (other.IsPersisted)
                        this.IsPersisted = other.IsPersisted;
                    this.DeletedAt = other.DeletedAt;
                }
                this.ModifiedAt = other.ModifiedAt;
                this.IsDirty = other.IsDirty;
            } finally {
                IsMerging = false;
            }
        }
 public ModelChangedMessage (Model model, string property) : base (model)
 {
     this.propertyName = property;
 }