public bool Remove(object o, INamedVersionedUniqueId p, string k)
        {
            if (o == null)
            {
                throw new ArgumentNullException("o");
            }
            if (p == null)
            {
                throw new ArgumentNullException("p");
            }
            if (k == null)
            {
                throw new ArgumentNullException("k");
            }

            SharedDictionaryEntry e = new SharedDictionaryEntry(o, p, k);
            SharedDictionaryEntry result;

            if (_values.TryGetValue(e, out result))
            {
                PluginConfigByObject co = _byObject[e.Obj];
                co.Remove(result);
                PluginConfigByPlugin cp = _byPlugin[e.PluginId.UniqueId];
                cp.Remove(result);
                _finalDictionary[e].Count--;
                _values.Remove(result);
                result.Value = null;
                if (Changed != null)
                {
                    Changed(this, new ConfigChangedEventArgs(e, e, ChangeStatus.Delete));
                }
                return(true);
            }
            return(false);
        }
        void DoRemove(object o, bool definitive)
        {
            PluginConfigByObject co;

            if (_byObject.TryGetValue(o, out co))
            {
                if (co.Count > 0)
                {
                    HashSet <INamedVersionedUniqueId> pluginsTouched = new HashSet <INamedVersionedUniqueId>();
                    foreach (SharedDictionaryEntry e in co)
                    {
                        _values.Remove(e);
                        PluginConfigByPlugin cp = _byPlugin[e.PluginId.UniqueId];
                        cp.Remove(e);
                        _finalDictionary.Remove(e);
                        // HashSet.Add simply returns false if the object already exists.
                        pluginsTouched.Add(e.PluginId);
                    }
                    co.Clear();
                    if (Changed != null)
                    {
                        bool allPluginsConcerned = pluginsTouched.Count == _byPlugin.Count;

                        ChangeStatus changeStatus;
                        if (definitive)
                        {
                            changeStatus = ChangeStatus.ContainerDestroy;
                        }
                        else
                        {
                            changeStatus = ChangeStatus.ContainerClear;
                        }

                        Changed(this, new ConfigChangedEventArgs(o, new ReadOnlyCollectionOnISet <INamedVersionedUniqueId>(pluginsTouched), allPluginsConcerned, changeStatus));
                    }
                }
                if (definitive)
                {
                    _byObject.Remove(o);
                }
            }
            // Clears fragment in any case (the object beeing known or not).
            ClearFragments(o);
        }
        /// <summary>
        /// Throws an ArgumentException if the Guid is already associated to
        /// another IVersionedUniqueId.
        /// </summary>
        private PluginConfigByPlugin CreatePluginConfigByPlugin(INamedVersionedUniqueId p)
        {
            PluginConfigByPlugin cp = new PluginConfigByPlugin(p);

            _byPlugin.Add(p.UniqueId, cp);
            var entriesToRemove = ClearFragments(_fragments.ToReadOnlyCollection(), f =>
            {
                if (f.PluginId == p.UniqueId)
                {
                    f.Restore(this, MergeMode.ErrorOnDuplicate);
                    return(true);
                }
                return(false);
            });

            foreach (object entry in entriesToRemove)
            {
                _fragments.Remove(entry);
            }
            return(cp);
        }
        public void Clear(object o, INamedVersionedUniqueId p)
        {
            if (o == null)
            {
                throw new ArgumentNullException("o");
            }
            if (p == null)
            {
                throw new ArgumentNullException("p");
            }

            FinalDictionary d;

            if (!_finalDictionary.TryGetValue(new SharedDictionaryEntry(o, p, null), out d) || d.Count == 0)
            {
                return;
            }
            PluginConfigByObject co = _byObject[o];
            PluginConfigByPlugin cp = _byPlugin[p.UniqueId];

            for (int i = 0; i < co.Count; ++i)
            {
                SharedDictionaryEntry e = co[i];
                if (e.PluginId == p)
                {
                    co.RemoveAt(i);
                    cp.Remove(e);
                    _values.Remove(e);
                }
            }
            d.Count = 0;
            if (Changed != null)
            {
                Changed(this, new ConfigChangedEventArgs(o, p, ChangeStatus.ContainerClear));
            }
        }