private void RegisterCommandHandlersForCommandsWithNoAssociatedHandler(FunctionHostBuilder builder, ICommandRegistry commandRegistry) { // IN PROGRESS: This looks from the loaded set of assemblies and looks for a command handler for each command associated with a function. // If the handler is not already registered in the command registry then this registers it. IRegistrationCatalogue registrationCatalogue = (IRegistrationCatalogue)commandRegistry; HashSet <Type> registeredCommandTypes = new HashSet <Type>(registrationCatalogue.GetRegisteredCommands()); Dictionary <Type, List <Type> > commandTypesToHandlerTypes = null; foreach (AbstractFunctionDefinition functionDefinition in builder.FunctionDefinitions) { if (registeredCommandTypes.Contains(functionDefinition.CommandType)) { continue; } if (commandTypesToHandlerTypes == null) { commandTypesToHandlerTypes = HarvestCommandHandlers(); } if (commandTypesToHandlerTypes.TryGetValue(functionDefinition.CommandType, out List <Type> handlerTypes)) { foreach (Type handlerType in handlerTypes) { commandRegistry.Register(handlerType); } } } }
private bool ValidateCommandTypes(FunctionHostBuilder builder) { // TODO: Add a check in the assembvly compile type checker to make sure that Negotiate<TCommand> type commands have a return type of SignalRNegotiateResponse ConstructorInfo constructor = builder.Options.MediatorTypeSafetyEnforcer.GetConstructor(new Type[0]); if (constructor == null) { _compilerLog.Error($"{builder.Options.MediatorTypeSafetyEnforcer.Name} does not have a default constructor. Implementations of IMediatorTypeSafetyEnforcer must have a default (parameterless) constructor."); return(false); } IMediatorTypeSafetyEnforcer typeSafetyEnforcer = (IMediatorTypeSafetyEnforcer)Activator.CreateInstance(builder.Options.MediatorTypeSafetyEnforcer); bool errorFound = false; foreach (AbstractFunctionDefinition functionDefinition in builder.FunctionDefinitions) { // SignalRBindingExpressionNegotiateCommand is a type used only to make a non dispatching HTTP function // definition work, it doesn't get used with any mediator and is defined within Function Monkey. It is // exempt from mediator type checking if (functionDefinition.CommandType != typeof(SignalRBindingExpressionNegotiateCommand) && functionDefinition.CommandType != typeof(SignalRClaimTypeNegotiateCommand)) { if (!typeSafetyEnforcer.IsValidType(functionDefinition.CommandType)) { errorFound = true; _compilerLog.Error($"Command type {functionDefinition.CommandType.Name} does not conform to the requirements of the mediator. {typeSafetyEnforcer.Requirements}"); } } } return(!errorFound); }
public void Patch(FunctionHostBuilder builder, string newAssemblyNamespace) { AuthorizationBuilder authorizationBuilder = (AuthorizationBuilder)builder.AuthorizationBuilder; Type validationResultType = typeof(ValidationResult); foreach (AbstractFunctionDefinition definition in builder.FunctionDefinitions) { definition.Namespace = newAssemblyNamespace; definition.IsUsingValidator = builder.ValidatorType != null; definition.CommandDeserializerType = definition.CommandDeserializerType ?? ((SerializationBuilder)(builder.SerializationBuilder)).DefaultCommandDeserializerType; if (CommandRequiresNoHandler(definition.CommandType)) { definition.NoCommandHandler = true; // don't skip the if statement, this may also be set through options } if (definition is HttpFunctionDefinition httpFunctionDefinition) { CompleteHttpFunctionDefinition(builder, httpFunctionDefinition, authorizationBuilder, validationResultType); } else if (definition is CosmosDbFunctionDefinition cosmosDbFunctionDefinition) { CompleteCosmosDbFunctionDefinition(cosmosDbFunctionDefinition); } } }
static Runtime() { ServiceCollection = new ServiceCollection(); CommandingDependencyResolverAdapter adapter = new CommandingDependencyResolverAdapter( (fromType, toInstance) => ServiceCollection.AddSingleton(fromType, toInstance), (fromType, toType) => ServiceCollection.AddTransient(fromType, toType), (resolveType) => ServiceProvider.GetService(resolveType) ); // Find the configuration implementation (IFunctionAppConfiguration configuration, ICommandRegistry commandRegistry) = LocateConfiguration(adapter); // Register internal implementations RegisterInternalImplementations(); // Invoke the builder process FunctionHostBuilder builder = CreateBuilderFromConfiguration(commandRegistry, configuration); FunctionBuilder functionBuilder = (FunctionBuilder)builder.FunctionBuilder; SetupAuthorization(builder, functionBuilder); RegisterTimerCommandFactories(ServiceCollection, builder.FunctionDefinitions); ServiceProvider = ServiceCollection.BuildServiceProvider(); builder.ServiceProviderCreatedAction?.Invoke(ServiceProvider); }
public void Compile() { IFunctionAppConfiguration configuration = ConfigurationLocator.FindConfiguration(_configurationSourceAssembly); if (configuration == null) { throw new ConfigurationException($"The assembly {_configurationSourceAssembly.GetName().Name} does not contain a public class implementing the IFunctionAppConfiguration interface"); } string newAssemblyNamespace = $"{_configurationSourceAssembly.GetName().Name}.Functions"; FunctionHostBuilder builder = new FunctionHostBuilder(_serviceCollection, _commandRegistry, false); configuration.Build(builder); new PostBuildPatcher().Patch(builder, newAssemblyNamespace); VerifyCommandAndResponseTypes(builder); IReadOnlyCollection <string> externalAssemblies = GetExternalAssemblyLocations(builder.FunctionDefinitions); OpenApiOutputModel openApi = _openApiCompiler.Compile(builder.OpenApiConfiguration, builder.FunctionDefinitions, _outputBinaryFolder); _jsonCompiler.Compile(builder.FunctionDefinitions, openApi, _outputBinaryFolder, newAssemblyNamespace); if (_outputProxiesJson && builder.AreProxiesEnabled) { _proxiesJsonCompiler.Compile(builder.FunctionDefinitions, builder.OpenApiConfiguration, openApi, _outputBinaryFolder); } _assemblyCompiler.Compile(builder.FunctionDefinitions, configuration.GetType(), newAssemblyNamespace, externalAssemblies, _outputBinaryFolder, $"{newAssemblyNamespace}.dll", openApi, _target, builder.OutputAuthoredSourceFolder); }
private void VerifyCommandAndResponseTypes(FunctionHostBuilder builder) { List <string> invalidTypes = new List <string>(); foreach (AbstractFunctionDefinition functionDefinition in builder.FunctionDefinitions) { if (!functionDefinition.CommandType.IsPublic) { invalidTypes.Add(functionDefinition.CommandType.Name); } if (functionDefinition.CommandResultType != null && !functionDefinition.CommandResultType.IsPublic) { invalidTypes.Add(functionDefinition.CommandResultType.FullName); } } if (invalidTypes.Count > 0) { StringBuilder sb = new StringBuilder(); sb.AppendLine("Commands and responses must be public. The following types are not:"); foreach (string invalidType in invalidTypes) { sb.AppendLine(invalidType); } throw new ConfigurationException(sb.ToString()); } }
private static FunctionHostBuilder CreateBuilderFromConfiguration(ICommandRegistry commandRegistry, IFunctionAppConfiguration configuration) { FunctionHostBuilder builder = new FunctionHostBuilder(ServiceCollection, commandRegistry, true); configuration.Build(builder); new PostBuildPatcher().Patch(builder, ""); return(builder); }
private static void CompleteHttpFunctionDefinition(FunctionHostBuilder builder, HttpFunctionDefinition httpFunctionDefinition, AuthorizationBuilder authorizationBuilder, Type validationResultType) { if (!httpFunctionDefinition.Authorization.HasValue) { httpFunctionDefinition.Authorization = authorizationBuilder.AuthorizationDefaultValue; } if (httpFunctionDefinition.Authorization.Value == AuthorizationTypeEnum.TokenValidation) { httpFunctionDefinition.ValidatesToken = true; } if (httpFunctionDefinition.Verbs.Count == 0) { httpFunctionDefinition.Verbs.Add(HttpMethod.Get); } httpFunctionDefinition.ClaimsPrincipalAuthorizationType = httpFunctionDefinition.ClaimsPrincipalAuthorizationType ?? httpFunctionDefinition.RouteConfiguration.ClaimsPrincipalAuthorizationType ?? authorizationBuilder.DefaultClaimsPrincipalAuthorizationType; httpFunctionDefinition.HeaderBindingConfiguration = httpFunctionDefinition.HeaderBindingConfiguration ?? builder.DefaultHeaderBindingConfiguration; httpFunctionDefinition.HttpResponseHandlerType = httpFunctionDefinition.HttpResponseHandlerType ?? builder.DefaultHttpResponseHandlerType; httpFunctionDefinition.TokenHeader = httpFunctionDefinition.TokenHeader ?? authorizationBuilder.AuthorizationHeader ?? "Authorization"; httpFunctionDefinition.IsValidationResult = httpFunctionDefinition.CommandResultType != null && validationResultType.IsAssignableFrom(httpFunctionDefinition .CommandResultType); httpFunctionDefinition.IsStreamCommand = (typeof(IStreamCommand)).IsAssignableFrom(httpFunctionDefinition.CommandType); httpFunctionDefinition.TokenValidatorType = httpFunctionDefinition.TokenValidatorType ?? authorizationBuilder.TokenValidatorType; if (httpFunctionDefinition.ValidatesToken && httpFunctionDefinition.TokenValidatorType == null) { throw new ConfigurationException($"Command {httpFunctionDefinition.CommandType.Name} expects to be authenticated with token validation but no token validator is registered"); } httpFunctionDefinition.Route = httpFunctionDefinition.Route?.TrimStart('/'); ExtractRouteParameters(httpFunctionDefinition); ExtractPossibleQueryParameters(httpFunctionDefinition); ExtractPossibleFormParameters(httpFunctionDefinition); EnsureOpenApiDescription(httpFunctionDefinition); }
private FunctionHostBuilder CreateBuilderFromConfiguration(ICommandRegistry commandRegistry, IFunctionAppConfiguration configuration) { FunctionHostBuilder builder = new FunctionHostBuilder(ServiceCollection, commandRegistry, true); configuration.Build(builder); RegisterCommandHandlersForCommandsWithNoAssociatedHandler(builder, commandRegistry); new PostBuildPatcher().Patch(builder, ""); return(builder); }
public RuntimeInstance(Assembly functionAppConfigurationAssembly, Action <IServiceCollection, ICommandRegistry> beforeServiceProviderBuild, Action <IServiceProvider, ICommandRegistry> afterServiceProviderBuild) { // Find the configuration implementation and service collection IFunctionAppConfiguration configuration = LocateConfiguration(functionAppConfigurationAssembly); IContainerProvider containerProvider = // ReSharper disable once SuspiciousTypeConversion.Global - externally provided (configuration as IContainerProvider) ?? new DefaultContainerProvider(); ServiceCollection = containerProvider.CreateServiceCollection(); CommandingDependencyResolverAdapter adapter = new CommandingDependencyResolverAdapter( (fromType, toInstance) => ServiceCollection.AddSingleton(fromType, toInstance), (fromType, toType) => ServiceCollection.AddTransient(fromType, toType), (resolveType) => ServiceProvider.GetService(resolveType) ); ICommandRegistry commandRegistry; // ReSharper disable once SuspiciousTypeConversion.Global - externally provided if (configuration is ICommandingConfigurator commandingConfigurator) { commandRegistry = commandingConfigurator.AddCommanding(adapter); } else { CommandingRuntime commandingRuntime = new CommandingRuntime(); commandRegistry = commandingRuntime.AddCommanding(adapter); } // Register internal implementations RegisterInternalImplementations(); // Invoke the builder process FunctionHostBuilder builder = CreateBuilderFromConfiguration(commandRegistry, configuration); Builder = builder; FunctionBuilder functionBuilder = (FunctionBuilder)builder.FunctionBuilder; SetupAuthorization(builder, functionBuilder); RegisterCoreDependencies(builder.FunctionDefinitions); RegisterTimerCommandFactories(builder.FunctionDefinitions); RegisterHttpDependencies(builder.FunctionDefinitions); RegisterCosmosDependencies(builder.FunctionDefinitions); beforeServiceProviderBuild?.Invoke(ServiceCollection, commandRegistry); ServiceProvider = containerProvider.CreateServiceProvider(ServiceCollection); afterServiceProviderBuild?.Invoke(ServiceProvider, commandRegistry); builder.ServiceProviderCreatedAction?.Invoke(ServiceProvider); }
private static void SetupAuthorization(FunctionHostBuilder builder, FunctionBuilder functionBuilder) { AuthorizationBuilder authorizationBuilder = (AuthorizationBuilder)builder.AuthorizationBuilder; // don't register the token validator type here - that gets passed down to the HTTP function // definitions to allow for function overrides and so is registered as part of HTTP dependencies ICommandClaimsBinder commandClaimsBinder = authorizationBuilder.ClaimsMappingBuilder.Build( functionBuilder.GetHttpFunctionDefinitions().Select(x => x.CommandType).ToArray()); ServiceCollection.AddSingleton(commandClaimsBinder); }
private static void SetupAuthorization(FunctionHostBuilder builder, FunctionBuilder functionBuilder) { AuthorizationBuilder authorizationBuilder = (AuthorizationBuilder)builder.AuthorizationBuilder; if (authorizationBuilder.TokenValidatorType != null) { ServiceCollection.AddTransient(typeof(ITokenValidator), authorizationBuilder.TokenValidatorType); } ICommandClaimsBinder commandClaimsBinder = authorizationBuilder.ClaimsMappingBuilder.Build( functionBuilder.GetHttpFunctionDefinitions().Select(x => x.CommandType).ToArray()); ServiceCollection.AddSingleton(commandClaimsBinder); }
private FunctionHostBuilder CreateBuilderFromConfiguration( ICommandRegistry commandRegistry, IFunctionAppConfiguration configuration) { FunctionHostBuilder builder = new FunctionHostBuilder(ServiceCollection, commandRegistry, true); configuration.Build(builder); DefaultMediatorSettings.SetDefaultsIfRequired(builder); RegisterCommandHandlersForCommandsWithNoAssociatedHandler(builder, commandRegistry); IMediatorResultTypeExtractor extractor = (IMediatorResultTypeExtractor)Activator.CreateInstance(builder.Options.MediatorResultTypeExtractor); new PostBuildPatcher(extractor).Patch(builder, ""); return(builder); }
public bool Compile() { string newAssemblyNamespace = $"{_configurationSourceAssembly.GetName().Name.Replace("-", "_")}.Functions"; IFunctionCompilerMetadata functionCompilerMetadata = null; IFunctionAppConfiguration configuration = ConfigurationLocator.FindConfiguration(_configurationSourceAssembly); if (configuration == null) { functionCompilerMetadata = ConfigurationLocator.FindCompilerMetadata(_configurationSourceAssembly); if (functionCompilerMetadata == null) { _compilerLog.Error($"The assembly {_configurationSourceAssembly.GetName().Name} does not contain a public class implementing the IFunctionAppConfiguration interface"); return(false); } } else { FunctionHostBuilder builder = new FunctionHostBuilder(_serviceCollection, _commandRegistry, false); configuration.Build(builder); new PostBuildPatcher().Patch(builder, newAssemblyNamespace); if (!VerifyCommandAndResponseTypes(builder)) { return(false); } functionCompilerMetadata = new FunctionCompilerMetadata { FunctionDefinitions = builder.FunctionDefinitions, OpenApiConfiguration = builder.OpenApiConfiguration, OutputAuthoredSourceFolder = builder.OutputAuthoredSourceFolder }; } IReadOnlyCollection <string> externalAssemblies = GetExternalAssemblyLocations(functionCompilerMetadata.FunctionDefinitions); OpenApiOutputModel openApi = _openApiCompiler.Compile(functionCompilerMetadata.OpenApiConfiguration, functionCompilerMetadata.FunctionDefinitions, _outputBinaryFolder); _jsonCompiler.Compile(functionCompilerMetadata.FunctionDefinitions, openApi, _outputBinaryFolder, newAssemblyNamespace); return(_assemblyCompiler.Compile(functionCompilerMetadata.FunctionDefinitions, configuration?.GetType() ?? functionCompilerMetadata.BacklinkReferenceType, configuration != null ? null : functionCompilerMetadata.BacklinkPropertyInfo, newAssemblyNamespace, externalAssemblies, _outputBinaryFolder, $"{newAssemblyNamespace}.dll", openApi, _compileTarget, functionCompilerMetadata.OutputAuthoredSourceFolder)); }
public static void SetDefaultsIfRequired(FunctionHostBuilder builder) { if (builder.Options.MediatorResultTypeExtractor == null) { builder.Options.MediatorResultTypeExtractor = typeof(DefaultMediatorResultTypeExtractor); } if (builder.Options.MediatorTypeSafetyEnforcer == null) { builder.Options.MediatorTypeSafetyEnforcer = typeof(DefaultMediatorTypeSafetyEnforcer); } if (builder.MediatorType == null) { builder.MediatorType = typeof(DefaultMediatorDecorator); } }
public void Patch(FunctionHostBuilder builder, string newAssemblyNamespace) { AuthorizationBuilder authorizationBuilder = (AuthorizationBuilder)builder.AuthorizationBuilder; Type validationResultType = typeof(ValidationResult); foreach (AbstractFunctionDefinition definition in builder.FunctionDefinitions) { definition.Namespace = newAssemblyNamespace; definition.IsUsingValidator = builder.ValidatorType != null; if (definition is HttpFunctionDefinition httpFunctionDefinition) { CompleteHttpFunctionDefinition(builder, httpFunctionDefinition, authorizationBuilder, validationResultType); } else if (definition is CosmosDbFunctionDefinition cosmosDbFunctionDefinition) { CompleteCosmosDbFunctionDefinition(cosmosDbFunctionDefinition); } } }
private static void CompleteHttpFunctionDefinition(FunctionHostBuilder builder, HttpFunctionDefinition httpFunctionDefinition, AuthorizationBuilder authorizationBuilder, Type validationResultType) { if (!httpFunctionDefinition.Authorization.HasValue) { httpFunctionDefinition.Authorization = authorizationBuilder.AuthorizationDefaultValue; } if (httpFunctionDefinition.Authorization.Value == AuthorizationTypeEnum.TokenValidation) { httpFunctionDefinition.ValidatesToken = true; } if (httpFunctionDefinition.Verbs.Count == 0) { httpFunctionDefinition.Verbs.Add(HttpMethod.Get); } if (string.IsNullOrWhiteSpace(httpFunctionDefinition.ClaimsPrincipalAuthorizationTypeName)) { httpFunctionDefinition.ClaimsPrincipalAuthorizationType = authorizationBuilder.DefaultClaimsPrincipalAuthorizationType; } httpFunctionDefinition.HeaderBindingConfiguration = httpFunctionDefinition.HeaderBindingConfiguration ?? builder.DefaultHeaderBindingConfiguration; httpFunctionDefinition.HttpResponseHandlerType = httpFunctionDefinition.HttpResponseHandlerType ?? builder.DefaultHttpResponseHandlerType; httpFunctionDefinition.TokenHeader = authorizationBuilder.AuthorizationHeader ?? "Authorization"; httpFunctionDefinition.IsValidationResult = httpFunctionDefinition.CommandResultType != null && validationResultType.IsAssignableFrom(httpFunctionDefinition .CommandResultType); ExtractPossibleQueryParameters(httpFunctionDefinition); ExtractRouteParameters(httpFunctionDefinition); EnsureOpenApiDescription(httpFunctionDefinition); }
private bool VerifyCommandAndResponseTypes(FunctionHostBuilder builder) { bool hasErrors = false; foreach (AbstractFunctionDefinition functionDefinition in builder.FunctionDefinitions) { if (!functionDefinition.CommandType.IsPublic) { _compilerLog.Error($"Command {functionDefinition.CommandType.FullName} must be public"); hasErrors = true; } if (functionDefinition.CommandResultType != null && !functionDefinition.CommandResultType.IsPublic) { _compilerLog.Error($"Command result type {functionDefinition.CommandResultType.FullName} must be public"); hasErrors = true; } } return(!hasErrors); }
public void Patch(FunctionHostBuilder builder, string newAssemblyNamespace) { AuthorizationBuilder authorizationBuilder = (AuthorizationBuilder)builder.AuthorizationBuilder; Type validationResultType = typeof(ValidationResult); foreach (AbstractFunctionDefinition definition in builder.FunctionDefinitions) { definition.Namespace = newAssemblyNamespace; definition.IsUsingValidator = builder.ValidatorType != null; if (definition is HttpFunctionDefinition httpFunctionDefinition) { if (!httpFunctionDefinition.Authorization.HasValue) { httpFunctionDefinition.Authorization = authorizationBuilder.AuthorizationDefaultValue; } if (httpFunctionDefinition.Authorization.Value == AuthorizationTypeEnum.TokenValidation) { httpFunctionDefinition.ValidatesToken = true; } if (httpFunctionDefinition.Verbs.Count == 0) { httpFunctionDefinition.Verbs.Add(HttpMethod.Get); } httpFunctionDefinition.TokenHeader = authorizationBuilder.AuthorizationHeader ?? "Authorization"; httpFunctionDefinition.IsValidationResult = httpFunctionDefinition.CommandResultType != null && validationResultType.IsAssignableFrom(httpFunctionDefinition.CommandResultType); ExtractPossibleQueryParameters(httpFunctionDefinition); ExtractRouteParameters(httpFunctionDefinition); EnsureOpenApiDescription(httpFunctionDefinition); } } }
private static void PatchHeaderBindings(FunctionHostBuilder builder, HttpFunctionDefinition httpFunctionDefinition) { if (httpFunctionDefinition.HeaderBindingConfiguration == null) { httpFunctionDefinition.HeaderBindingConfiguration = builder.DefaultHeaderBindingConfiguration; } else { if (builder.DefaultHeaderBindingConfiguration != null) { foreach (KeyValuePair <string, string> kvp in builder.DefaultHeaderBindingConfiguration .PropertyFromHeaderMappings) { if (!httpFunctionDefinition.HeaderBindingConfiguration.PropertyFromHeaderMappings.ContainsKey( kvp.Key)) { httpFunctionDefinition.HeaderBindingConfiguration.PropertyFromHeaderMappings .Add(kvp.Key, kvp.Value); } } } } if (httpFunctionDefinition.HeaderBindingConfiguration == null) { httpFunctionDefinition.HeaderBindingConfiguration = new HeaderBindingConfiguration() { PropertyFromHeaderMappings = new Dictionary <string, string>() }; } if (httpFunctionDefinition.HeaderBindingConfiguration.PropertyFromHeaderMappings == null) { httpFunctionDefinition.HeaderBindingConfiguration.PropertyFromHeaderMappings = new Dictionary <string, string>(); } }
private void RegisterCommandHandlersForCommandsWithNoAssociatedHandler(FunctionHostBuilder builder, ICommandRegistry commandRegistry) { // TODO: We can improve this so that auto-registration is decoupled and can be provided by a mediator package if (builder.MediatorType != typeof(DefaultMediatorDecorator)) { return; } // IN PROGRESS: This looks from the loaded set of assemblies and looks for a command handler for each command associated with a function. // If the handler is not already registered in the command registry then this registers it. IRegistrationCatalogue registrationCatalogue = (IRegistrationCatalogue)commandRegistry; HashSet <Type> registeredCommandTypes = new HashSet <Type>(registrationCatalogue.GetRegisteredCommands()); Dictionary <Type, List <Type> > commandTypesToHandlerTypes = null; foreach (AbstractFunctionDefinition functionDefinition in builder.FunctionDefinitions) { if (registeredCommandTypes.Contains(functionDefinition.CommandType)) { continue; } if (commandTypesToHandlerTypes == null) { commandTypesToHandlerTypes = HarvestCommandHandlers(); } if (commandTypesToHandlerTypes.TryGetValue(functionDefinition.CommandType, out List <Type> handlerTypes)) { foreach (Type handlerType in handlerTypes) { commandRegistry.Register(handlerType); } } } }
public RuntimeInstance(Assembly functionAppConfigurationAssembly, Action <IServiceCollection, ICommandRegistry> beforeServiceProviderBuild, IServiceCollection serviceCollection) { ServiceCollection = serviceCollection ?? new ServiceCollection(); BuiltServiceProvider = new Lazy <IServiceProvider>(() => ServiceCollection.BuildServiceProvider()); // Find the configuration implementation and service collection IFunctionAppConfiguration configuration = LocateConfiguration(functionAppConfigurationAssembly); CommandingDependencyResolverAdapter adapter = new CommandingDependencyResolverAdapter( (fromType, toInstance) => ServiceCollection.AddSingleton(fromType, toInstance), (fromType, toType) => ServiceCollection.AddTransient(fromType, toType), resolveType => ServiceProvider.GetService(resolveType) ); ICommandRegistry commandRegistry; // ReSharper disable once SuspiciousTypeConversion.Global - externally provided if (configuration != null && configuration is ICommandingConfigurator commandingConfigurator) { commandRegistry = commandingConfigurator.AddCommanding(adapter); } else { CommandingRuntime commandingRuntime = new CommandingRuntime(); commandRegistry = commandingRuntime.AddCommanding(adapter); } // Register internal implementations RegisterInternalImplementations(); FunctionHostBuilder builder = null; IFunctionCompilerMetadata functionCompilerMetadata = null; if (configuration != null) { // Invoke the builder process builder = CreateBuilderFromConfiguration(commandRegistry, configuration); FunctionBuilder functionBuilder = (FunctionBuilder)builder.FunctionBuilder; FunctionDefinitions = builder.FunctionDefinitions; SetupAuthorization(builder, functionBuilder); } else { functionCompilerMetadata = LocateFunctionCompilerMetadata(functionAppConfigurationAssembly); FunctionDefinitions = functionCompilerMetadata.FunctionDefinitions; } RegisterCoreDependencies(FunctionDefinitions); RegisterTimerCommandFactories(FunctionDefinitions); RegisterHttpDependencies(FunctionDefinitions); RegisterCosmosDependencies(FunctionDefinitions); CreatePluginFunctions(functionCompilerMetadata?.ClaimsMappings, FunctionDefinitions); //beforeServiceProviderBuild?.Invoke(ServiceCollection, commandRegistry); //ServiceProvider = containerProvider.CreateServiceProvider(ServiceCollection); //afterServiceProviderBuild?.Invoke(ServiceProvider, commandRegistry); //builder?.ServiceProviderCreatedAction?.Invoke(ServiceProvider); }
public bool Compile() { string newAssemblyNamespace = $"{_configurationSourceAssembly.GetName().Name.Replace("-", "_")}.Functions"; IFunctionCompilerMetadata functionCompilerMetadata = null; IFunctionAppConfiguration configuration = null; FunctionAppHostBuilder appHostBuilder = null; IFunctionAppHost appHost = ConfigurationLocator.FindFunctionAppHost(_configurationSourceAssembly); if (appHost != null) { appHostBuilder = new FunctionAppHostBuilder(); appHost.Build(appHostBuilder); if (appHostBuilder.FunctionAppConfiguration != null) { configuration = (IFunctionAppConfiguration)Activator.CreateInstance(appHostBuilder.FunctionAppConfiguration); } } if (configuration == null) { configuration = ConfigurationLocator.FindConfiguration(_configurationSourceAssembly); } if (configuration == null) { functionCompilerMetadata = ConfigurationLocator.FindCompilerMetadata(_configurationSourceAssembly); if (functionCompilerMetadata == null) { _compilerLog.Error($"The assembly {_configurationSourceAssembly.GetName().Name} does not contain a public class implementing the IFunctionAppConfiguration interface"); return(false); } } else { FunctionHostBuilder builder = new FunctionHostBuilder(_serviceCollection, _commandRegistry, false); if (appHostBuilder != null) { builder.Options = appHostBuilder.Options; } configuration.Build(builder); DefaultMediatorSettings.SetDefaultsIfRequired(builder); if (!ValidateCommandTypes(builder)) { return(false); } IMediatorResultTypeExtractor extractor = CreateMediatorResultTypeExtractor(builder.Options.MediatorResultTypeExtractor); if (extractor == null) { return(false); } new PostBuildPatcher(extractor).Patch(builder, newAssemblyNamespace); if (!VerifyCommandAndResponseTypes(builder)) { return(false); } if (!VerifyOutputBindings(builder)) { return(false); } functionCompilerMetadata = new FunctionCompilerMetadata { FunctionDefinitions = builder.FunctionDefinitions, OpenApiConfiguration = builder.OpenApiConfiguration, OutputAuthoredSourceFolder = builder.Options.OutputSourceTo, CompilerOptions = builder.Options }; } PostBuildPatcher.EnsureFunctionsHaveUniqueNames(functionCompilerMetadata.FunctionDefinitions); IReadOnlyCollection <string> externalAssemblies = GetExternalAssemblyLocations(functionCompilerMetadata.FunctionDefinitions); ITargetCompiler targetCompiler = functionCompilerMetadata.CompilerOptions.HttpTarget == CompileTargetEnum.AzureFunctions ? (ITargetCompiler) new AzureFunctionsCompiler(_compilerLog) : new AspNetCoreCompiler(_compilerLog); return(targetCompiler.CompileAssets(functionCompilerMetadata, newAssemblyNamespace, configuration, externalAssemblies, _outputBinaryFolder)); }
public RuntimeInstance(Assembly functionAppConfigurationAssembly, Action <IServiceCollection, ICommandRegistry> beforeServiceProviderBuild, IServiceCollection serviceCollection) { if (serviceCollection == null) { System.Console.WriteLine("No service collection supplied by runtime"); } ServiceCollection = serviceCollection ?? new ServiceCollection(); BuiltServiceProvider = new Lazy <IServiceProvider>(() => ServiceCollection.BuildServiceProvider()); FunctionAppHostBuilder appHostBuilder = null; IFunctionAppConfiguration configuration = null; IFunctionAppHost appHost = ConfigurationLocator.FindFunctionAppHost(functionAppConfigurationAssembly); if (appHost != null) { appHostBuilder = new FunctionAppHostBuilder(); appHost.Build(appHostBuilder); if (appHostBuilder.FunctionAppConfiguration != null) { configuration = (IFunctionAppConfiguration)Activator.CreateInstance(appHostBuilder.FunctionAppConfiguration); } } if (configuration == null) { configuration = ConfigurationLocator.FindConfiguration(functionAppConfigurationAssembly); } CommandingDependencyResolverAdapter adapter = new CommandingDependencyResolverAdapter( (fromType, toInstance) => ServiceCollection.AddSingleton(fromType, toInstance), (fromType, toType) => ServiceCollection.AddTransient(fromType, toType), resolveType => ServiceProvider.GetService(resolveType) ); ICommandRegistry commandRegistry; // ReSharper disable once SuspiciousTypeConversion.Global - externally provided if (configuration != null && configuration is ICommandingConfigurator commandingConfigurator) { commandRegistry = commandingConfigurator.AddCommanding(adapter); } else { CommandingRuntime commandingRuntime = new CommandingRuntime(); commandRegistry = commandingRuntime.AddCommanding(adapter); } // Register internal implementations RegisterInternalImplementations(); FunctionHostBuilder builder = null; IFunctionCompilerMetadata functionCompilerMetadata = null; CompileTargetEnum compileTarget; if (configuration != null) { // Invoke the builder process builder = CreateBuilderFromConfiguration(commandRegistry, configuration); if (appHostBuilder != null) { builder.Options = appHostBuilder.Options; } FunctionBuilder functionBuilder = (FunctionBuilder)builder.FunctionBuilder; FunctionDefinitions = builder.FunctionDefinitions; compileTarget = builder.Options.HttpTarget; SetupAuthorization(builder, functionBuilder); } else { functionCompilerMetadata = LocateFunctionCompilerMetadata(functionAppConfigurationAssembly); FunctionDefinitions = functionCompilerMetadata.FunctionDefinitions; compileTarget = functionCompilerMetadata.CompilerOptions.HttpTarget; } PostBuildPatcher.EnsureFunctionsHaveUniqueNames(FunctionDefinitions); RegisterCoreDependencies(builder?.MediatorType ?? typeof(DefaultMediatorDecorator), FunctionDefinitions, compileTarget); RegisterTimerCommandFactories(FunctionDefinitions); RegisterHttpDependencies(FunctionDefinitions); RegisterCosmosDependencies(FunctionDefinitions); RegisterOutputBindingDependencies(FunctionDefinitions); CreatePluginFunctions(functionCompilerMetadata?.ClaimsMappings, FunctionDefinitions); RegisterLoggerIfRequired(); }