File: ServiceDescriptor.cs
Web Access
Project: src\src\Workspaces\Remote\Core\Microsoft.CodeAnalysis.Remote.Workspaces.csproj (Microsoft.CodeAnalysis.Remote.Workspaces)
// 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;
using Microsoft.ServiceHub.Framework;
using StreamJsonRpc;
 
namespace Microsoft.CodeAnalysis.Remote;
 
/// <summary>
/// Describes Roslyn remote brokered service. 
/// Adds Roslyn specific JSON converters and RPC settings to the default implementation.
/// </summary>
internal sealed class ServiceDescriptor : ServiceJsonRpcDescriptor
{
    /// <summary>
    /// Brokered services must be defined in Microsoft.VisualStudio service namespace in order to be considered first party.
    /// </summary>
    internal const string ServiceNameTopLevelPrefix = "Microsoft.VisualStudio.";
 
    private static readonly JsonRpcTargetOptions s_jsonRpcTargetOptions = new()
    {
        // Do not allow JSON-RPC to automatically subscribe to events and remote their calls.
        NotifyClientOfEvents = false,
 
        // Only allow public methods (may be on internal types) to be invoked remotely.
        AllowNonPublicInvocation = false
    };
 
    internal readonly string ComponentName;
    internal readonly string SimpleName;
 
    private readonly Func<string, string> _featureDisplayNameProvider;
    private readonly RemoteSerializationOptions _serializationOptions;
 
    private ServiceDescriptor(
        ServiceMoniker serviceMoniker,
        string componentName,
        string simpleName,
        RemoteSerializationOptions serializationOptions,
        Func<string, string> displayNameProvider,
        Type? clientInterface)
        : base(serviceMoniker, clientInterface, serializationOptions.Formatter, serializationOptions.MessageDelimiters, serializationOptions.MultiplexingStreamOptions)
    {
        ComponentName = componentName;
        SimpleName = simpleName;
        _featureDisplayNameProvider = displayNameProvider;
        _serializationOptions = serializationOptions;
    }
 
    private ServiceDescriptor(ServiceDescriptor copyFrom)
      : base(copyFrom)
    {
        ComponentName = copyFrom.ComponentName;
        SimpleName = copyFrom.SimpleName;
        _featureDisplayNameProvider = copyFrom._featureDisplayNameProvider;
        _serializationOptions = copyFrom._serializationOptions;
    }
 
    public static ServiceDescriptor CreateRemoteServiceDescriptor(string componentName, string simpleName, string suffix, RemoteSerializationOptions options, Func<string, string> featureDisplayNameProvider, Type? clientInterface)
        => new(CreateMoniker(componentName, simpleName, suffix), componentName, simpleName, options, featureDisplayNameProvider, clientInterface);
 
    public static ServiceDescriptor CreateInProcServiceDescriptor(string componentName, string simpleName, string suffix, Func<string, string> featureDisplayNameProvider)
        => new(CreateMoniker(componentName, simpleName, suffix), componentName, simpleName, RemoteSerializationOptions.Default, featureDisplayNameProvider, clientInterface: null);
 
    private static ServiceMoniker CreateMoniker(string componentName, string simpleName, string suffix)
        => new(ServiceNameTopLevelPrefix + componentName + "." + simpleName + suffix);
 
    protected override ServiceRpcDescriptor Clone()
        => new ServiceDescriptor(this);
 
    protected override IJsonRpcMessageFormatter CreateFormatter()
        => _serializationOptions.ConfigureFormatter(base.CreateFormatter());
 
    protected override JsonRpcConnection CreateConnection(JsonRpc jsonRpc)
    {
        jsonRpc.CancelLocallyInvokedMethodsWhenConnectionIsClosed = true;
        var connection = base.CreateConnection(jsonRpc);
        connection.LocalRpcTargetOptions = s_jsonRpcTargetOptions;
        return connection;
    }
 
    internal string GetFeatureDisplayName()
        => _featureDisplayNameProvider(SimpleName);
}