| File: Internal\ExtensionMessageHandlerFactory.cs | Web Access |
| Project: src\roslyn\src\Features\ExternalAccess\Extensions\Microsoft.CodeAnalysis.ExternalAccess.Extensions.csproj (Microsoft.CodeAnalysis.ExternalAccess.Extensions) |
// 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 System.Collections.Immutable; using System.Composition; using System.Reflection; using System.Threading; using Microsoft.CodeAnalysis.ExternalAccess.Extensions; using Microsoft.CodeAnalysis.Host.Mef; namespace Microsoft.CodeAnalysis.Extensions; [ExportWorkspaceService(typeof(IExtensionMessageHandlerFactory)), Shared] [method: ImportingConstructor] [method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] internal sealed class ExtensionMessageHandlerFactory() : IExtensionMessageHandlerFactory { public ImmutableArray<IExtensionMessageHandlerWrapper<Document>> CreateDocumentMessageHandlers( Assembly assembly, string extensionIdentifier, CancellationToken cancellationToken) => CreateWorkspaceHandlers( assembly, typeof(IExtensionDocumentMessageHandler<,>), (handler, handlerInterface) => new ExtensionDocumentMessageHandlerWrapper(handler, handlerInterface, extensionIdentifier), cancellationToken); public ImmutableArray<IExtensionMessageHandlerWrapper<Solution>> CreateWorkspaceMessageHandlers( Assembly assembly, string extensionIdentifier, CancellationToken cancellationToken) => CreateWorkspaceHandlers( assembly, typeof(IExtensionWorkspaceMessageHandler<,>), (handler, handlerInterface) => new ExtensionWorkspaceMessageHandlerWrapper(handler, handlerInterface, extensionIdentifier), cancellationToken); private static ImmutableArray<IExtensionMessageHandlerWrapper<TArgument>> CreateWorkspaceHandlers<TArgument>( Assembly assembly, Type unboundInterfaceType, Func<object, Type, IExtensionMessageHandlerWrapper<TArgument>> wrapperCreator, CancellationToken cancellationToken) { var resultBuilder = ImmutableArray.CreateBuilder<IExtensionMessageHandlerWrapper<TArgument>>(); foreach (var candidateType in assembly.GetTypes()) { cancellationToken.ThrowIfCancellationRequested(); if (candidateType.IsAbstract || candidateType.IsGenericType) continue; Type? boundInterfaceType = null; foreach (var interfaceType in candidateType.GetInterfaces()) { if (interfaceType.IsGenericType && !interfaceType.IsGenericTypeDefinition && interfaceType.GetGenericTypeDefinition() == unboundInterfaceType) { if (boundInterfaceType is not null) throw new InvalidOperationException(string.Format(ExternalAccessExtensionsResources.Type_0_implements_interface_1_more_than_once, candidateType.FullName, unboundInterfaceType.Name)); boundInterfaceType = interfaceType; } } if (boundInterfaceType == null) continue; var handler = Activator.CreateInstance(candidateType) ?? throw new InvalidOperationException(string.Format(ExternalAccessExtensionsResources.Cannot_create_0, candidateType.FullName)); resultBuilder.Add(wrapperCreator(handler, boundInterfaceType)); } return resultBuilder.ToImmutable(); } }