예제 #1
0
        public DependencyVertex <TKey, TValue> AddOrUpdate(TKey key, TValue value, ImmutableArray <TKey> incomingKeys)
        {
            var version = Snapshot.Version + 1;

            DependencyVertex <TKey, TValue> changedVertex;

            if (_verticesByKey.TryGetValue(key, out var currentVertex))
            {
                changedVertex = new DependencyVertex <TKey, TValue>(currentVertex, value, incomingKeys, version);
                _verticesByIndex[changedVertex.Index] = changedVertex;
            }
            else
            {
                changedVertex = new DependencyVertex <TKey, TValue>(key, value, incomingKeys, version, _verticesByIndex.Count);
                _verticesByIndex.Add(changedVertex);
            }

            _verticesByKey[key] = changedVertex;


            var vertices = _verticesByIndex
                           .Where(v => !v.IsSealed || v.HasMissingKeys)
                           .Select(v => GetOrCreateNonSealedVertex(version, v.Index))
                           .ToArray();

            if (vertices.Length == 0)
            {
                Snapshot = new DependencyGraphSnapshot <TKey, TValue>(version);
                return(changedVertex);
            }

            CreateNewSnapshot(vertices, version);

            return(changedVertex);
        }
예제 #2
0
        private void CreateNewSnapshot(IEnumerable <DependencyVertex <TKey, TValue> > vertices, int version)
        {
            var missingKeysHashSet = new HashSet <TKey>();

            foreach (var vertex in vertices)
            {
                var newIncoming = ImmutableArray <int> .Empty;
                var oldIncoming = vertex.Incoming;

                foreach (var dependencyKey in vertex.IncomingKeys)
                {
                    if (_verticesByKey.TryGetValue(dependencyKey, out var dependency))
                    {
                        newIncoming = newIncoming.Add(dependency.Index);
                    }
                    else
                    {
                        missingKeysHashSet.Add(dependencyKey);
                        vertex.SetHasMissingKeys();
                    }
                }

                foreach (var index in oldIncoming.Except(newIncoming))
                {
                    var incomingVertex = GetOrCreateNonSealedVertex(version, index);
                    incomingVertex.RemoveOutgoing(vertex.Index);
                }

                foreach (var index in newIncoming.Except(oldIncoming))
                {
                    var incomingVertex = GetOrCreateNonSealedVertex(version, index);
                    incomingVertex.AddOutgoing(vertex.Index);
                }

                vertex.SetIncoming(newIncoming);
            }

            foreach (var vertex in _verticesByIndex)
            {
                vertex.Seal();
            }

            Snapshot = new DependencyGraphSnapshot <TKey, TValue>(version,
                                                                  ImmutableArray <DependencyVertex <TKey, TValue> > .Create(_verticesByIndex),
                                                                  ImmutableArray <TKey> .Create(missingKeysHashSet));
        }
예제 #3
0
        private static IDependencyChainWalker <TKey, TValue> CreateDependencyChainWalker(
            DependencyResolver <TKey, TValue> dependencyResolver,
            DependencyGraphSnapshot <TKey, TValue> snapshot,
            ImmutableArray <DependencyVertex <TKey, TValue> > changedVertices)
        {
            var walkingGraph   = CreateWalkingGraph(snapshot.Vertices, changedVertices);
            var affectedValues = walkingGraph.Select(v => v.DependencyVertex.Value);

            var loopsCount = FindLoops(walkingGraph);

            var(startingVertices, totalNodesCount) = ResolveLoops(walkingGraph, loopsCount);
            foreach (var vertex in walkingGraph)
            {
                vertex.Seal();
                vertex.SecondPass?.Seal();
            }

            return(new DependencyChainWalker(dependencyResolver, startingVertices, affectedValues, snapshot.MissingKeys, totalNodesCount, snapshot.Version));
        }
        public DependencyVertex <TKey, TValue> AddOrUpdate(TKey key, TValue value, ImmutableArray <TKey> incomingKeys)
        {
            var version = Snapshot.Version + 1;

            DependencyVertex <TKey, TValue> changedVertex;

            if (_verticesByKey.TryGetValue(key, out var currentVertex))
            {
                changedVertex = new DependencyVertex <TKey, TValue>(currentVertex, value, incomingKeys, version);
                _verticesByIndex[changedVertex.Index] = changedVertex;
            }
            else
            {
                changedVertex = new DependencyVertex <TKey, TValue>(key, value, incomingKeys, version, _verticesByIndex.Count);
                _verticesByIndex.Add(changedVertex);
            }

            _verticesByKey[key] = changedVertex;

            var missingKeysHashSet = new HashSet <TKey>();
            var vertices           = _verticesByIndex
                                     .Where(v => !v.IsSealed || v.HasMissingKeys)
                                     .Select(v => GetOrCreateNonSealedVertex(version, v.Index))
                                     .ToArray();

            if (vertices.Length == 0)
            {
                Snapshot = new DependencyGraphSnapshot <TKey, TValue>(version);
                return(changedVertex);
            }

            foreach (var vertex in vertices)
            {
                var newIncoming = ImmutableArray <int> .Empty;
                var oldIncoming = vertex.Incoming;

                foreach (var dependencyKey in vertex.IncomingKeys)
                {
                    if (_verticesByKey.TryGetValue(dependencyKey, out var dependency))
                    {
                        newIncoming = newIncoming.Add(dependency.Index);
                    }
                    else
                    {
                        missingKeysHashSet.Add(dependencyKey);
                        vertex.SetHasMissingKeys();
                    }
                }

                foreach (var index in oldIncoming.Except(newIncoming))
                {
                    var incomingVertex = GetOrCreateNonSealedVertex(version, index);
                    incomingVertex.RemoveOutgoing(vertex.Index);
                }

                foreach (var index in newIncoming.Except(oldIncoming))
                {
                    var incomingVertex = GetOrCreateNonSealedVertex(version, index);
                    incomingVertex.AddOutgoing(vertex.Index);
                }

                vertex.SetIncoming(newIncoming);
            }

            foreach (var vertex in _verticesByIndex)
            {
                vertex.Seal();
            }

            Snapshot = new DependencyGraphSnapshot <TKey, TValue>(version,
                                                                  ImmutableArray <DependencyVertex <TKey, TValue> > .Create(_verticesByIndex),
                                                                  ImmutableArray <TKey> .Create(missingKeysHashSet));

            return(changedVertex);
        }
 public DependencyGraph()
 {
     Snapshot = new DependencyGraphSnapshot <TKey, TValue>(0);
 }