public void RegisterSnapshotProvider(IDependenciesSnapshotProvider snapshotProvider) { if (snapshotProvider == null) { return; } lock (_snapshotProviders) { _snapshotProviders[snapshotProvider.CurrentSnapshot.ProjectPath] = snapshotProvider; snapshotProvider.SnapshotRenamed += OnSnapshotRenamed; snapshotProvider.SnapshotChanged += OnSnapshotChanged; snapshotProvider.SnapshotProviderUnloading += OnSnapshotProviderUnloading; } void OnSnapshotProviderUnloading(object sender, SnapshotProviderUnloadingEventArgs e) { // Project has unloaded, so remove it from the cache and unregister event handlers SnapshotProviderUnloading?.Invoke(this, e); lock (_snapshotProviders) { _snapshotProviders.Remove(snapshotProvider.CurrentSnapshot.ProjectPath); snapshotProvider.SnapshotRenamed -= OnSnapshotRenamed; snapshotProvider.SnapshotChanged -= OnSnapshotChanged; snapshotProvider.SnapshotProviderUnloading -= OnSnapshotProviderUnloading; } } void OnSnapshotRenamed(object sender, ProjectRenamedEventArgs e) { lock (_snapshotProviders) { // Remove and re-add provider with new project path if (!string.IsNullOrEmpty(e.OldFullPath) && _snapshotProviders.TryGetValue(e.OldFullPath, out IDependenciesSnapshotProvider provider) && _snapshotProviders.Remove(e.OldFullPath) && provider != null && !string.IsNullOrEmpty(e.NewFullPath)) { _snapshotProviders[e.NewFullPath] = provider; } } } void OnSnapshotChanged(object sender, SnapshotChangedEventArgs e) { // Propagate the change event SnapshotChanged?.Invoke(this, e); } }
private Task OnUnconfiguredProjectUnloading(object sender, EventArgs args) { CommonServices.Project.ProjectUnloading -= OnUnconfiguredProjectUnloading; SnapshotProviderUnloading?.Invoke(this, new SnapshotProviderUnloadingEventArgs(this)); foreach (var subscriber in DependencySubscribers) { subscriber.Value.DependenciesChanged -= OnSubscriberDependenciesChanged; } foreach (var provider in SubTreeProviders) { provider.Value.DependenciesChanged -= OnSubtreeProviderDependenciesChanged; } return(Task.CompletedTask); }
/// <summary> /// When a given project context is unloaded, remove it form the cache and unregister event handlers /// </summary> internal void OnSnapshotProviderUnloading(object sender, SnapshotProviderUnloadingEventArgs e) { IDependenciesSnapshotProvider snapshotProvider = e.SnapshotProvider; if (snapshotProvider == null) { return; } SnapshotProviderUnloading?.Invoke(this, e); lock (_snapshotProvidersLock) { SnapshotProviders.TryRemove(snapshotProvider.ProjectFilePath, out IDependenciesSnapshotProvider provider); snapshotProvider.SnapshotRenamed -= OnSnapshotRenamed; snapshotProvider.SnapshotChanged -= OnSnapshotChanged; snapshotProvider.SnapshotProviderUnloading -= OnSnapshotProviderUnloading; } }
private Task OnUnconfiguredProjectUnloadingAsync(object sender, EventArgs args) { _commonServices.Project.ProjectUnloading -= OnUnconfiguredProjectUnloadingAsync; _commonServices.Project.ProjectRenamed -= OnUnconfiguredProjectRenamedAsync; SnapshotProviderUnloading?.Invoke(this, new SnapshotProviderUnloadingEventArgs(this)); foreach (Lazy <IDependencyCrossTargetSubscriber, IOrderPrecedenceMetadataView> subscriber in _dependencySubscribers) { subscriber.Value.DependenciesChanged -= OnSubscriberDependenciesChanged; } foreach (Lazy <IProjectDependenciesSubTreeProvider, IOrderPrecedenceMetadataView> provider in _subTreeProviders) { provider.Value.DependenciesChanged -= OnSubtreeProviderDependenciesChanged; } return(Task.CompletedTask); }
/// <inheritdoc /> public IDisposable RegisterSnapshotProvider(IDependenciesSnapshotProvider snapshotProvider) { Requires.NotNull(snapshotProvider, nameof(snapshotProvider)); var unregister = new DisposableBag(); lock (_lock) { snapshotProvider.SnapshotRenamed += OnSnapshotRenamed; snapshotProvider.SnapshotProviderUnloading += OnSnapshotProviderUnloading; ITargetBlock <SnapshotChangedEventArgs> actionBlock = DataflowBlockSlim.CreateActionBlock <SnapshotChangedEventArgs>( e => SnapshotChanged?.Invoke(this, e), "AggregateDependenciesSnapshotProviderSource {1}", skipIntermediateInputData: true); unregister.Add( snapshotProvider.SnapshotChangedSource.LinkTo( actionBlock, DataflowOption.PropagateCompletion)); _snapshotProviderByPath = _snapshotProviderByPath.SetItem(snapshotProvider.CurrentSnapshot.ProjectPath, snapshotProvider); } unregister.Add(new DisposableDelegate( () => { lock (_lock) { string projectPath = snapshotProvider.CurrentSnapshot.ProjectPath; _snapshotProviderByPath = _snapshotProviderByPath.Remove(projectPath); snapshotProvider.SnapshotRenamed -= OnSnapshotRenamed; snapshotProvider.SnapshotProviderUnloading -= OnSnapshotProviderUnloading; } })); return(unregister); void OnSnapshotProviderUnloading(object sender, SnapshotProviderUnloadingEventArgs e) { // Project has unloaded, so remove it from the cache and unregister event handlers SnapshotProviderUnloading?.Invoke(this, e); unregister.Dispose(); } void OnSnapshotRenamed(object sender, ProjectRenamedEventArgs e) { if (string.IsNullOrEmpty(e.OldFullPath)) { return; } lock (_lock) { // Remove and re-add provider with new project path if (_snapshotProviderByPath.TryGetValue(e.OldFullPath, out IDependenciesSnapshotProvider provider)) { _snapshotProviderByPath = _snapshotProviderByPath.Remove(e.OldFullPath); if (!string.IsNullOrEmpty(e.NewFullPath)) { _snapshotProviderByPath = _snapshotProviderByPath.SetItem(e.NewFullPath, provider); } } } } }
/// <inheritdoc /> protected override async Task InitializeCoreAsync(CancellationToken cancellationToken) { await UpdateProjectContextAndSubscriptionsAsync(); lock (_lock) { if (_isDisposed) { throw new ObjectDisposedException(nameof(DependenciesSnapshotProvider)); } IDisposable unregister = _aggregateSnapshotProvider.RegisterSnapshotProvider(this); _disposables.Add(unregister); _commonServices.Project.ProjectUnloading += OnUnconfiguredProjectUnloadingAsync; _commonServices.Project.ProjectRenamed += OnUnconfiguredProjectRenamedAsync; foreach (Lazy <IProjectDependenciesSubTreeProvider, IOrderPrecedenceMetadataView> provider in _subTreeProviders) { provider.Value.DependenciesChanged += OnSubtreeProviderDependenciesChanged; } _disposables.Add( new DisposableDelegate( () => { _commonServices.Project.ProjectUnloading -= OnUnconfiguredProjectUnloadingAsync; _commonServices.Project.ProjectRenamed -= OnUnconfiguredProjectRenamedAsync; foreach (Lazy <IProjectDependenciesSubTreeProvider, IOrderPrecedenceMetadataView> provider in _subTreeProviders) { provider.Value.DependenciesChanged -= OnSubtreeProviderDependenciesChanged; } })); } return; Task OnUnconfiguredProjectUnloadingAsync(object sender, EventArgs args) { // If our project unloads, we have no more work to do. Notify listeners and clean everything up. SnapshotProviderUnloading?.Invoke(this, new SnapshotProviderUnloadingEventArgs(this)); DisposeCore(); return(Task.CompletedTask); } Task OnUnconfiguredProjectRenamedAsync(object sender, ProjectRenamedEventArgs e) { SnapshotRenamed?.Invoke(this, e); return(Task.CompletedTask); } void OnSubtreeProviderDependenciesChanged(object sender, DependenciesChangedEventArgs e) { if (IsDisposing || IsDisposed || !e.Changes.AnyChanges()) { return; } ITargetFramework targetFramework = string.IsNullOrEmpty(e.TargetShortOrFullName) || TargetFramework.Any.Equals(e.TargetShortOrFullName) ? TargetFramework.Any : _targetFrameworkProvider.GetTargetFramework(e.TargetShortOrFullName !) ?? TargetFramework.Any; UpdateDependenciesSnapshot(targetFramework, e.Changes, catalogs: null, targetFrameworks: default, activeTargetFramework: null, e.Token);