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); }
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)); }
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); }