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);
                    }
                }
            }
        }
Beispiel #2
0
        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);
                }
            }
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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());
            }
        }
Beispiel #7
0
        private static FunctionHostBuilder CreateBuilderFromConfiguration(ICommandRegistry commandRegistry,
                                                                          IFunctionAppConfiguration configuration)
        {
            FunctionHostBuilder builder = new FunctionHostBuilder(ServiceCollection, commandRegistry, true);

            configuration.Build(builder);
            new PostBuildPatcher().Patch(builder, "");
            return(builder);
        }
Beispiel #8
0
        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);
        }
Beispiel #11
0
        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);
        }
Beispiel #12
0
        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);
        }
Beispiel #13
0
        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);
        }
Beispiel #14
0
        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);
        }
Beispiel #18
0
        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);
                }
            }
        }
Beispiel #20
0
        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>();
            }
        }
Beispiel #21
0
        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);
        }
Beispiel #23
0
        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));
        }
Beispiel #24
0
        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();
        }