File: BrokeredServices\BrokeredServiceContainer.cs
Web Access
Project: src\src\LanguageServer\Microsoft.CodeAnalysis.LanguageServer\Microsoft.CodeAnalysis.LanguageServer.csproj (Microsoft.CodeAnalysis.LanguageServer)
// 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.
 
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services;
using Microsoft.ServiceHub.Framework;
using Microsoft.ServiceHub.Framework.Services;
using Microsoft.VisualStudio.Composition;
using Microsoft.VisualStudio.Threading;
using Microsoft.VisualStudio.Utilities.ServiceBroker;
 
namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices;
internal class BrokeredServiceContainer : GlobalBrokeredServiceContainer
{
    public BrokeredServiceContainer(TraceSource traceSource)
        : base(ImmutableDictionary<ServiceMoniker, ServiceRegistration>.Empty, isClientOfExclusiveServer: false, joinableTaskFactory: null, traceSource)
    {
    }
 
    public override IReadOnlyDictionary<string, string> LocalUserCredentials
        => ImmutableDictionary<string, string>.Empty;
 
    /// <inheritdoc cref="GlobalBrokeredServiceContainer.RegisterServices(IReadOnlyDictionary{ServiceMoniker, ServiceRegistration})"/>
    internal new void RegisterServices(IReadOnlyDictionary<ServiceMoniker, ServiceRegistration> services)
        => base.RegisterServices(services);
 
    /// <inheritdoc cref="GlobalBrokeredServiceContainer.UnregisterServices(IEnumerable{ServiceMoniker})"/>
    internal new void UnregisterServices(IEnumerable<ServiceMoniker> services)
        => base.UnregisterServices(services);
 
    internal ImmutableDictionary<ServiceMoniker, ServiceRegistration> GetRegisteredServices()
        => RegisteredServices;
 
    internal static async Task<BrokeredServiceContainer> CreateAsync(ExportProvider exportProvider, CancellationToken cancellationToken)
    {
        var traceListener = exportProvider.GetExportedValue<BrokeredServiceTraceListener>();
        var container = new BrokeredServiceContainer(traceListener.Source);
 
        container.ProfferIntrinsicService(
            FrameworkServices.Authorization,
            new ServiceRegistration(VisualStudio.Shell.ServiceBroker.ServiceAudience.Local, null, allowGuestClients: true),
            (moniker, options, serviceBroker, cancellationToken) => new(new NoOpAuthorizationService()));
 
        var mefServiceBroker = exportProvider.GetExportedValue<MefServiceBrokerOfExportedServices>();
        mefServiceBroker.SetContainer(container);
 
        // Register local mef services.
        await mefServiceBroker.RegisterAndProfferServicesAsync(cancellationToken);
 
        // Register the desired remote services
        container.RegisterServices(Descriptors.RemoteServicesToRegister);
 
        return container;
    }
 
    private class NoOpAuthorizationService : IAuthorizationService
    {
        public event EventHandler? CredentialsChanged;
 
        public event EventHandler? AuthorizationChanged;
 
        public ValueTask<bool> CheckAuthorizationAsync(ProtectedOperation operation, CancellationToken cancellationToken = default)
        {
            return new(true);
        }
 
        public ValueTask<IReadOnlyDictionary<string, string>> GetCredentialsAsync(CancellationToken cancellationToken = default)
        {
            return new(ImmutableDictionary<string, string>.Empty);
        }
 
        protected virtual void OnCredentialsChanged(EventArgs args) => this.CredentialsChanged?.Invoke(this, args);
 
        protected virtual void OnAuthorizationChanged(EventArgs args) => this.AuthorizationChanged?.Invoke(this, args);
    }
}