File: Workspace\VisualStudioAddMetadataReferenceCodeActionOperationFactoryWorkspaceService.cs
Web Access
Project: src\src\VisualStudio\Core\Def\Microsoft.VisualStudio.LanguageServices_pxr0p0dn_wpftmp.csproj (Microsoft.VisualStudio.LanguageServices)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System;
using System.Composition;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeActions.WorkspaceServices;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell.Interop;
 
namespace Microsoft.VisualStudio.LanguageServices.Implementation;
 
[ExportWorkspaceService(typeof(IAddMetadataReferenceCodeActionOperationFactoryWorkspaceService), ServiceLayer.Host), Shared]
internal sealed class VisualStudioAddMetadataReferenceCodeActionOperationFactoryWorkspaceService : IAddMetadataReferenceCodeActionOperationFactoryWorkspaceService
{
    [ImportingConstructor]
    [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
    public VisualStudioAddMetadataReferenceCodeActionOperationFactoryWorkspaceService()
    {
    }
 
    public CodeActionOperation CreateAddMetadataReferenceOperation(ProjectId projectId, AssemblyIdentity assemblyIdentity)
    {
        if (projectId == null)
        {
            throw new ArgumentNullException(nameof(projectId));
        }
 
        if (assemblyIdentity == null)
        {
            throw new ArgumentNullException(nameof(assemblyIdentity));
        }
 
        return new AddMetadataReferenceOperation(projectId, assemblyIdentity);
    }
 
    private class AddMetadataReferenceOperation : CodeActionOperation
    {
        private readonly AssemblyIdentity _assemblyIdentity;
        private readonly ProjectId _projectId;
 
        public AddMetadataReferenceOperation(ProjectId projectId, AssemblyIdentity assemblyIdentity)
        {
            _projectId = projectId;
            _assemblyIdentity = assemblyIdentity;
        }
 
        public override void Apply(Workspace workspace, CancellationToken cancellationToken = default)
        {
            var visualStudioWorkspace = (VisualStudioWorkspaceImpl)workspace;
            if (!visualStudioWorkspace.TryAddReferenceToProject(_projectId, "*" + _assemblyIdentity.GetDisplayName()))
            {
                // We failed to add the reference, which means the project system wasn't able to bind.
                // We'll pop up the Add Reference dialog to let the user figure this out themselves.
                // This is the same approach done in CVBErrorFixApply::ApplyAddMetaReferenceFix
 
                if (visualStudioWorkspace.GetHierarchy(_projectId) is IVsUIHierarchy uiHierarchy)
                {
                    var command = new OLECMD[1];
                    command[0].cmdID = (uint)VSConstants.VSStd2KCmdID.ADDREFERENCE;
 
                    if (ErrorHandler.Succeeded(uiHierarchy.QueryStatusCommand((uint)VSConstants.VSITEMID.Root, VSConstants.VSStd2K, 1, command, IntPtr.Zero)))
                    {
                        if ((((OLECMDF)command[0].cmdf) & OLECMDF.OLECMDF_ENABLED) != 0)
                        {
                            uiHierarchy.ExecCommand((uint)VSConstants.VSITEMID.Root, VSConstants.VSStd2K, (uint)VSConstants.VSStd2KCmdID.ADDREFERENCE, 0, IntPtr.Zero, IntPtr.Zero);
                        }
                    }
                }
            }
        }
 
        public override string Title
            => string.Format(ServicesVSResources.Add_a_reference_to_0, _assemblyIdentity.GetDisplayName());
    }
}