public IEnumerable <AggregationResult> Modify(IEnumerable <object> facts)
        {
            var keys         = new List <TKey>();
            var resultLookup = new DefaultKeyMap <TKey, AggregationResult>();

            foreach (var fact in facts)
            {
                var source     = (TSource)fact;
                var key        = _keySelector(source);
                var element    = _elementSelector(source);
                var oldKey     = _sourceToKey[fact];
                var oldElement = _sourceToElement[fact];
                _sourceToKey[fact]     = key;
                _sourceToElement[fact] = element;

                if (Equals(key, oldKey))
                {
                    var result = Modify(key, element);
                    if (!resultLookup.ContainsKey(key))
                    {
                        keys.Add(key);
                        resultLookup[key] = result;
                    }
                }
                else
                {
                    var result1 = Remove(oldKey, oldElement);
                    if (!resultLookup.ContainsKey(oldKey))
                    {
                        keys.Add(oldKey);
                    }
                    resultLookup[oldKey] = result1;

                    var result2 = Add(key, element);
                    AggregationResult previousResult;
                    if (!resultLookup.TryGetValue(key, out previousResult))
                    {
                        keys.Add(key);
                        resultLookup[key] = result2;
                    }
                    else if (previousResult.Action == AggregationAction.Removed ||
                             result2.Action == AggregationAction.Added)
                    {
                        resultLookup[key] = AggregationResult.Modified(previousResult.Aggregate);
                    }
                }
            }
            var results = GetResults(keys, resultLookup);

            return(results);
        }
        public IEnumerable <AggregationResult> Remove(IEnumerable <object> facts)
        {
            var keys         = new List <TKey>();
            var resultLookup = new DefaultKeyMap <TKey, AggregationResult>();

            foreach (var fact in facts)
            {
                var oldKey     = _sourceToKey[fact];
                var oldElement = _sourceToElement[fact];
                _sourceToKey.Remove(fact);
                _sourceToElement.Remove(fact);
                var result = Remove(oldKey, oldElement);
                if (!resultLookup.ContainsKey(oldKey))
                {
                    keys.Add(oldKey);
                }
                resultLookup[oldKey] = result;
            }
            var results = GetResults(keys, resultLookup);

            return(results);
        }
        public IEnumerable <AggregationResult> Add(IEnumerable <object> facts)
        {
            var keys         = new List <TKey>();
            var resultLookup = new DefaultKeyMap <TKey, AggregationResult>();

            foreach (var fact in facts)
            {
                var source  = (TSource)fact;
                var key     = _keySelector(source);
                var element = _elementSelector(source);
                _sourceToKey[fact]     = key;
                _sourceToElement[fact] = element;
                var result = Add(key, element);
                if (!resultLookup.ContainsKey(key))
                {
                    keys.Add(key);
                    resultLookup[key] = result;
                }
            }
            var results = GetResults(keys, resultLookup);

            return(results);
        }
        private static IEnumerable <AggregationResult> GetResults(IEnumerable <TKey> keys, DefaultKeyMap <TKey, AggregationResult> lookup)
        {
            var results = new List <AggregationResult>();

            foreach (var key in keys)
            {
                var result = lookup[key];
                results.Add(result);
            }
            return(results);
        }