public void TestConcurrentDictionaring1()
        {
            ObservableCollection <Item> items = new ObservableCollection <Item>(
                new Item[]
            {
                new Item(0, "0"),
                new Item(1, "1"),
                new Item(2, "2")
            });

            OcConsumer consumer = new OcConsumer();
            ConcurrentDictionaring <Item, int, string> dictionaring =
                items.ConcurrentDictionaring(i => i.Id, i => i.Value).For(consumer);

            Assert.Throws <ObservableComputationsException>(() => items.Add(new Item(0, "2")));

            consumer.Dispose();
        }
        public void TestConcurrentDictionaring()
        {
            ObservableCollection <Item> items = new ObservableCollection <Item>(
                new Item[]
            {
                new Item(0, "0"),
                new Item(1, "1"),
                new Item(2, "2")
            });

            NotifyCollectionChangedEventArgs lastNotifyCollectionChangedEventArgs = null;

            items.CollectionChanged += (sender, args) =>
            {
                lastNotifyCollectionChangedEventArgs = args;
            };

            OcConsumer consumer = new OcConsumer();
            ConcurrentDictionaring <Item, int, string> dictionaring =
                items.ConcurrentDictionaring(i => new Computing <int>(() => i.Id).Value, i => new Computing <string>(() => i.Value).Value);

            bool activationInProgress   = true;
            bool inActivationInProgress = false;

            dictionaring.PropertyChanged += (sender, args) =>
            {
                if (args.PropertyName == "ActivationInProgress" || args.PropertyName == "InactivationInProgress")
                {
                    return;
                }
                Assert.AreEqual(dictionaring.ActivationInProgress, activationInProgress);
                Assert.AreEqual(dictionaring.InactivationInProgress, inActivationInProgress);
            };

            dictionaring.For(consumer);
            activationInProgress = false;

            if (OcConfiguration.SaveInstantiationStackTrace)
            {
                Assert.IsNotNull(dictionaring.InstantiationStackTrace);
            }

            Assert.IsNotNull(dictionaring.ToString());

            Assert.IsNull(dictionaring.UserCodeIsCalledFrom);

            Assert.IsTrue(((IComputingInternal)dictionaring).Consumers.Contains(consumer));

            dictionaring.DebugTag = "DebugTag";
            Assert.AreEqual(dictionaring.DebugTag, "DebugTag");

            dictionaring.Tag = "Tag";
            Assert.AreEqual(dictionaring.Tag, "Tag");

            Assert.IsTrue(dictionaring.IsActive);

            Assert.IsTrue(dictionaring.IsConsistent);

            Assert.IsNotNull(dictionaring.ToString());

            Assert.NotNull(dictionaring.GetEnumerator());
            Assert.NotNull(((IEnumerable)dictionaring).GetEnumerator());
            dictionaring.CopyTo(new KeyValuePair <int, string> [3], 0);
            Assert.NotNull(dictionaring.ToString());

            Assert.IsTrue(dictionaring.Contains(new KeyValuePair <int, string>(0, "0")));
            Assert.IsFalse(dictionaring.IsReadOnly);
            Assert.IsTrue(dictionaring.TryGetValue(0, out string value0));
            Assert.AreEqual(value0, "0");
            Assert.IsTrue(dictionaring.Values.SequenceEqual(items.Select(i => i.Value)));

            int    changedKey              = 0;
            string changedValue            = null;
            bool   getValueOrDefaultRaised = false;
            bool   itemRaised              = false;
            bool   containsKeyRaised       = false;

            dictionaring.MethodChanged += (sender, args) =>
            {
                if (args.MethodName == "GetValueOrDefault" && args.ArgumentsPredicate(new object[] { changedKey, changedValue }))
                {
                    getValueOrDefaultRaised = true;
                }
                if (args.MethodName == "Item[]" && args.ArgumentsPredicate(new object[] { changedKey, changedValue }))
                {
                    itemRaised = true;
                }
                if (args.MethodName == "ContainsKey" && args.ArgumentsPredicate(new object[] { changedKey, changedValue }))
                {
                    containsKeyRaised = true;
                }

                if (dictionaring.HandledEventArgs is NotifyCollectionChangedEventArgs)
                {
                    Assert.AreEqual(dictionaring.HandledEventSender, dictionaring.Source);
                    Assert.AreEqual(dictionaring.HandledEventArgs, lastNotifyCollectionChangedEventArgs);
                }
            };

            Action <int, string> dictionaringAddItemRequestHandler = (id, value) => items.Add(new Item(id, value));

            dictionaring.AddItemRequestHandler = dictionaringAddItemRequestHandler;
            Assert.IsTrue(dictionaring.AddItemRequestHandler == dictionaringAddItemRequestHandler);

            Action <int, string> dictionaringSetItemRequestHandler = (id, value) => items.SingleOrDefault(i => i.Id == id).Value = value;

            dictionaring.SetItemRequestHandler = dictionaringSetItemRequestHandler;
            Assert.IsTrue(dictionaring.SetItemRequestHandler == dictionaringSetItemRequestHandler);

            Func <int, bool> dictionaringRemoveItemRequestHandler = id => items.Remove(items.SingleOrDefault(i => i.Id == id));

            dictionaring.RemoveItemRequestHandler = dictionaringRemoveItemRequestHandler;
            Assert.IsTrue(dictionaring.RemoveItemRequestHandler == dictionaringRemoveItemRequestHandler);

            Action dictionaringClearItemsRequestHandler = () => items.Clear();

            dictionaring.ClearItemsRequestHandler = dictionaringClearItemsRequestHandler;
            Assert.IsTrue(dictionaring.ClearItemsRequestHandler == dictionaringClearItemsRequestHandler);

            changedKey   = 5;
            changedValue = "2";
            dictionaring.Add(5, "2");
            dictionaring.ValidateInternalConsistency();
            Assert.IsTrue(getValueOrDefaultRaised);
            Assert.IsTrue(itemRaised);
            Assert.IsTrue(containsKeyRaised);

            Assert.IsTrue(dictionaring.Contains(new KeyValuePair <int, string>(5, "2")));

            getValueOrDefaultRaised = false;
            itemRaised        = false;
            containsKeyRaised = false;
            changedKey        = 7;
            changedValue      = "7";
            dictionaring.Add(new KeyValuePair <int, string>(7, "7"));
            dictionaring.ValidateInternalConsistency();
            Assert.IsTrue(getValueOrDefaultRaised);
            Assert.IsTrue(itemRaised);
            Assert.IsTrue(containsKeyRaised);

            Assert.AreEqual(dictionaring.GetValueOrDefault(5), "2");
            Assert.AreEqual(dictionaring.GetValueOrDefault(-5), null);

            getValueOrDefaultRaised = false;
            itemRaised        = false;
            containsKeyRaised = false;
            changedKey        = 5;
            changedValue      = "2";
            Assert.IsTrue(dictionaring.Remove(5));
            dictionaring.ValidateInternalConsistency();
            Assert.IsTrue(getValueOrDefaultRaised);
            Assert.IsTrue(itemRaised);
            Assert.IsTrue(containsKeyRaised);


            getValueOrDefaultRaised = false;
            itemRaised        = false;
            containsKeyRaised = false;
            Assert.IsFalse(dictionaring.Remove(10));
            dictionaring.ValidateInternalConsistency();
            Assert.IsFalse(getValueOrDefaultRaised);
            Assert.IsFalse(itemRaised);
            Assert.IsFalse(containsKeyRaised);

            getValueOrDefaultRaised = false;
            itemRaised        = false;
            containsKeyRaised = false;
            changedKey        = 7;
            changedValue      = "7";
            Assert.IsTrue(dictionaring.Remove(new KeyValuePair <int, string>(7, "7")));
            dictionaring.ValidateInternalConsistency();
            Assert.IsTrue(getValueOrDefaultRaised);
            Assert.IsTrue(itemRaised);
            Assert.IsTrue(containsKeyRaised);

            getValueOrDefaultRaised = false;
            itemRaised        = false;
            containsKeyRaised = false;
            Assert.IsFalse(dictionaring.Remove(new KeyValuePair <int, string>(8, "8")));
            dictionaring.ValidateInternalConsistency();
            Assert.IsFalse(getValueOrDefaultRaised);
            Assert.IsFalse(itemRaised);
            Assert.IsFalse(containsKeyRaised);

            getValueOrDefaultRaised = false;
            itemRaised        = false;
            containsKeyRaised = false;
            Assert.IsFalse(dictionaring.Remove(new KeyValuePair <int, string>(7, "88")));
            dictionaring.ValidateInternalConsistency();
            Assert.IsFalse(getValueOrDefaultRaised);
            Assert.IsFalse(itemRaised);
            Assert.IsFalse(containsKeyRaised);

            getValueOrDefaultRaised = false;
            itemRaised        = false;
            containsKeyRaised = false;
            Assert.IsFalse(dictionaring.Remove(new KeyValuePair <int, string>(2, "3")));
            dictionaring.ValidateInternalConsistency();
            Assert.IsFalse(getValueOrDefaultRaised);
            Assert.IsFalse(itemRaised);
            Assert.IsFalse(containsKeyRaised);

            getValueOrDefaultRaised = false;
            itemRaised        = false;
            containsKeyRaised = false;
            changedKey        = 0;
            changedValue      = "0";
            dictionaring[0]   = "1";
            dictionaring.ValidateInternalConsistency();
            Assert.IsTrue(getValueOrDefaultRaised);
            Assert.IsTrue(itemRaised);
            Assert.IsTrue(containsKeyRaised);

            Assert.IsTrue(getValueOrDefaultRaised);
            Assert.IsTrue(itemRaised);
            Assert.IsTrue(containsKeyRaised);
            dictionaring.Clear();
            dictionaring.ValidateInternalConsistency();
            Assert.IsTrue(getValueOrDefaultRaised);
            Assert.IsTrue(itemRaised);
            Assert.IsTrue(containsKeyRaised);

            inActivationInProgress = true;
            consumer.Dispose();
        }