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);
        }
Beispiel #3
0
        /// <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;
            }
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        /// <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);