예제 #1
0
        /// <summary>
        /// Adds references to one or more assembly files.
        /// </summary>
        public async Task AddAsync(params string[] assemblyFileNames)
        {
            // Note: This method does not need to be async, but it's written
            // this way to be consistent with the other `AddAsync` methods.
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            IVsReferenceManagerUser     manager = GetManager();
            IVsReferenceProviderContext context;

            // Which provider context we need to use will depend on the type
            // of project style. Classic projects use assembly references,
            // and SDK-style projects use file references.
            if (TryGetProviderContext(manager, out IVsFileReferenceProviderContext fileContext))
            {
                context = fileContext;
            }
            else if (TryGetProviderContext(manager, out IVsAssemblyReferenceProviderContext assemblyContext))
            {
                context = assemblyContext;
            }
            else
            {
                throw new NotSupportedException($"The project '{_project.Name}' cannot have assembly references.");
            }

            foreach (string fileName in assemblyFileNames)
            {
                IVsReference reference = context.CreateReference();
                reference.Name     = Path.GetFileNameWithoutExtension(fileName);
                reference.FullPath = fileName;
                context.AddReference(reference);
            }

            manager.ChangeReferences((uint)__VSREFERENCECHANGEOPERATION.VSREFERENCECHANGEOPERATION_ADD, context);
        }
예제 #2
0
        private T GetProviderContext <T>(IVsReferenceManagerUser manager) where T : IVsReferenceProviderContext
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            if (!TryGetProviderContext <T>(manager, out T context))
            {
                throw new NotSupportedException($"Could not find the {typeof(T).Name} for the project.");
            }

            return(context);
        }
예제 #3
0
        private bool TryGetProviderContext <T>(IVsReferenceManagerUser manager, out T context) where T : IVsReferenceProviderContext
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            T?value = manager.GetProviderContexts().OfType <T>().FirstOrDefault();

            if (value is not null)
            {
                context = value;
                return(true);
            }

            context = default !;
예제 #4
0
        /// <summary>
        /// Adds references to one or more projects.
        /// </summary>
        public async Task AddAsync(params Project[] projects)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            IVsSolution solution = await VS.Services.GetSolutionAsync();

            IVsReferenceManagerUser manager = GetManager();
            Lazy <IVsProjectReferenceProviderContext>       projectContext = new(() => GetProviderContext <IVsProjectReferenceProviderContext>(manager), false);
            Lazy <IVsSharedProjectReferenceProviderContext> sharedContext  = new(() => GetProviderContext <IVsSharedProjectReferenceProviderContext>(manager), false);

            foreach (Project project in projects)
            {
                project.GetItemInfo(out IVsHierarchy hierarchy, out uint itemId, out _);

                IVsSharedAssetsProject?sharedProject = hierarchy.GetSharedAssetsProject();
                if (sharedProject is not null)
                {
                    IVsSharedProjectReference reference = (IVsSharedProjectReference)sharedContext.Value.CreateReference();
                    PopulateSharedProjectReference(reference, solution, project, sharedProject);
                    sharedContext.Value.AddReference(reference);
                }
                else
                {
                    ErrorHandler.ThrowOnFailure(solution.GetUniqueNameOfProject(hierarchy, out string uniqueName));
                    ErrorHandler.ThrowOnFailure(solution.GetGuidOfProject(hierarchy, out Guid projectGuid));

                    IVsProjectReference reference = (IVsProjectReference)projectContext.Value.CreateReference();
                    reference.Name     = project.Name;
                    reference.FullPath = project.FullPath;
                    reference.Identity = projectGuid.ToString("b");
                    // The reference specification is made up of the project’s GUID and the
                    // project's Visual Studio unique name, separated by a "|" character.
                    reference.ReferenceSpecification = $"{projectGuid:b}|{uniqueName}";
                    projectContext.Value.AddReference(reference);
                }
            }

            if (projectContext.IsValueCreated)
            {
                manager.ChangeReferences((uint)__VSREFERENCECHANGEOPERATION.VSREFERENCECHANGEOPERATION_ADD, projectContext.Value);
            }

            if (sharedContext.IsValueCreated)
            {
                manager.ChangeReferences((uint)__VSREFERENCECHANGEOPERATION.VSREFERENCECHANGEOPERATION_ADD, sharedContext.Value);
            }
        }
예제 #5
0
        private bool TryGetManager(out IVsReferenceManagerUser manager)
        {
            _project.GetItemInfo(out IVsHierarchy hierarchy, out uint itemId, out _);

            IVsReferenceManagerUser?value = HierarchyUtilities.GetHierarchyProperty <IVsReferenceManagerUser?>(
                hierarchy,
                itemId,
                (int)__VSHPROPID5.VSHPROPID_ReferenceManagerUser
                );

            if (value is not null)
            {
                manager = value;
                return(true);
            }

            manager = null !;
            return(false);
        }
예제 #6
0
        /// <summary>
        /// Removes the given references from the project.
        /// </summary>
        /// <param name="references">The references to remove.</param>
        /// <returns>A task.</returns>
        public async Task RemoveAsync(params Reference[] references)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            // There doesn't seem to be an easy way to actually remove references from a project.
            // There is no direct way to map an `IVsReference` instance to the provider that handles
            // that type of reference, and the `IVsReferenceProviderContext` has no way to remove a
            // reference from its `References` property. What we do here might seem like a bit of a hack,
            // but it appears to work fine.
            //
            // We start by creating a mapping from an `IVsReference` type to the corresponding provider
            // context by getting each provider context to create a reference object. The provider
            // context just creates a new object and doesn't seem to do anything with it, so this
            // shouldn't have any side effects. This gives us a way to get the provider context
            // that an `IVsReference` object is handled by.
            //
            // But, the provider contexts from the manager contain all of the existing references with no
            // way to remove reference objects from them, so we can't pass those contexts to the manager
            // when calling `ChangeReferences()` because that will remove all existing references!
            // What we will do is create an instance of our own implementation of a provider context
            // so that the provider context will only contain the references that we want to remove.
            Dictionary <Type, RemovingReferenceProviderContext> contextsByReferenceType = new();
            IVsReferenceManagerUser manager = GetManager();

            foreach (IVsReferenceProviderContext context in manager.GetProviderContexts().OfType <IVsReferenceProviderContext>())
            {
                contextsByReferenceType[context.CreateReference().GetType()] = new RemovingReferenceProviderContext(context.ProviderGuid);
            }

            foreach (Reference reference in references)
            {
                if (contextsByReferenceType.TryGetValue(reference.VsReference.GetType(), out RemovingReferenceProviderContext context))
                {
                    context.AddReference(reference.VsReference);
                }
            }

            foreach (IVsReferenceProviderContext context in contextsByReferenceType.Values.Where((x) => x.HasReferences))
            {
                manager.ChangeReferences((uint)__VSREFERENCECHANGEOPERATION.VSREFERENCECHANGEOPERATION_REMOVE, context);
            }
        }