public static void SetEnvVariables(StartupConfiguration configuration)
        {
            var fullLogsPath = Path.IsPathRooted(configuration.LogsPath)
                ? configuration.LogsPath
                : Path.Combine(AppDomain.CurrentDomain.BaseDirectory, configuration.LogsPath);

            var flatProfileName = configuration.Profile?.CleanFileName().Replace(Path.DirectorySeparatorChar, '_');

            Environment.SetEnvironmentVariable("LogsPath", fullLogsPath, EnvironmentVariableTarget.Process);
            Environment.SetEnvironmentVariable("ProfileName", flatProfileName, EnvironmentVariableTarget.Process);
            Environment.SetEnvironmentVariable("Profile", configuration.Profile, EnvironmentVariableTarget.Process);
            Environment.SetEnvironmentVariable("ConfigurationPath", configuration.ConfigurationPath, EnvironmentVariableTarget.Process);
            Environment.SetEnvironmentVariable("InstanceId", configuration.InstanceId, EnvironmentVariableTarget.Process);
        }
        /// <summary>
        /// Составляем приложение.
        /// </summary>
        /// <param name="startupConfiguration">Параметры запуска приложения.</param>
        /// <returns>Провайдер к коллекции зарегистрированных сервисов.</returns>
        public IBuildContext Build(StartupConfiguration startupConfiguration)
        {
            _buildContext = new BuildContext {
                StartupConfiguration = startupConfiguration,
            };
            var measureSession = new MeasureSession("Application startup");

            // Разбор параметров командной строки
            if (startupConfiguration.SetPropertiesFromCommandLineArgs)
            {
                startupConfiguration.BuildUpFromCommandLineArgs(startupConfiguration.CommandLineArgs.Args);
            }

            SetEnvVariables(startupConfiguration);

            // Can use defined service collection or create new
            _buildContext.ServiceCollection = startupConfiguration.ServiceCollection ?? new ServiceCollection();
            var serviceCollection = _buildContext.ServiceCollection;

            using (measureSession.StartTimer("ConfigureLogging"))
            {
                // Получение сконфигурированной фабрики логирования.
                var configureLogging = startupConfiguration.ConfigureLogging ?? DefaultLogging.ConfigureLogging;
                _buildContext.LoggerFactory = configureLogging();
                _buildContext.Logger        = _buildContext.LoggerFactory.CreateLogger("Bootstrap");
            }

            using (measureSession.StartTimer("LoadTypes"))
            {
                // Получение информации об окружении.
                _buildContext.StartupInfo = ReflectionUtils.GetStartupInfo();

                // Переключим текущую директорию на директорию запуска.
                Directory.SetCurrentDirectory(_buildContext.StartupInfo.BaseDirectory);
                _buildContext.StartupInfo.CurrentDirectory = _buildContext.StartupInfo.BaseDirectory;

                // Загрузка сборок в память
                _buildContext.Assemblies = ReflectionUtils
                                           .LoadAssemblies(_buildContext.StartupInfo.BaseDirectory, _buildContext.StartupConfiguration.AssemblyScanPatterns)
                                           .Concat(new[] { typeof(ApplicationBuilder).Assembly })
                                           .Distinct()
                                           .ToArray();

                _buildContext.Logger.LogDebug($"Loaded {_buildContext.Assemblies.Length} assemblies");

                if (_buildContext.Assemblies.Length > 20)
                {
                    var assemblyScanPatterns     = _buildContext.StartupConfiguration.AssemblyScanPatterns;
                    var assemblyScanPatternsText = string.Join(",", assemblyScanPatterns);
                    _buildContext.Logger.LogWarning($"Diagnostic: too many assemblies found. Specify AssemblyScanPatterns. Loaded: {_buildContext.Assemblies.Length} assemblies, AssemblyScanPatterns: {assemblyScanPatternsText}");
                }

                // Список типов
                _buildContext.ExportedTypes = _buildContext.Assemblies.SelectMany(assembly => assembly.GetDefinedTypesSafe()).ToArray();

                _buildContext.LogHeader();//todo: assemblies loaded? types loaded
            }

            using (measureSession.StartTimer("LoadConfiguration"))
            {
                // Загрузка конфигурации
                ConfigurationReader.LoadConfiguration(_buildContext);

                // Регистрируем конфигурацию в виде IConfiguration и IConfigurationRoot
                serviceCollection.Replace(ServiceDescriptor.Singleton <IConfiguration>(_buildContext.ConfigurationRoot));
                serviceCollection.Replace(ServiceDescriptor.Singleton <IConfigurationRoot>(_buildContext.ConfigurationRoot));
            }

            using (measureSession.StartTimer("ConfigureServices"))
            {
                try
                {
                    // Конфигурирование сервисов
                    ConfigureServices(_buildContext);

                    // Строим провайдер.
                    _buildContext.ServiceProvider = _buildContext.ServiceCollection.BuildServiceProvider();
                }
                catch (Exception exception)
                {
                    _buildContext.Logger.LogError(new EventId(0), exception, exception.Message);
                    throw;
                }
            }

            // Dump значений конфигурации в лог
            if (startupConfiguration.DumpConfigurationToLog)
            {
                _buildContext.ConfigurationRoot.DumpConfigurationToLog(_buildContext.LoggerFactory, startupConfiguration.IsSecretConfigurationKey, "Configuration");
            }

            measureSession.LogMeasures(_buildContext.Logger);

            return(_buildContext);
        }
        /// <summary>
        /// Составляем и запускаем приложение.
        /// </summary>
        /// <param name="startupConfiguration">Параметры запуска приложения.</param>
        /// <returns>Провайдер к коллекции зарегистрированных сервисов.</returns>
        public IServiceProvider BuildAndStart(StartupConfiguration startupConfiguration)
        {
            var buildContext = Build(startupConfiguration);

            return(Start(buildContext));
        }
        /// <summary>
        /// Конфигурирование сервисов.
        /// </summary>
        /// <param name="buildContext">Контекст построения приложения.</param>
        public void ConfigureServices(BuildContext buildContext)
        {
            var logger = buildContext.Logger;

            StartupConfiguration startupConfiguration = buildContext.StartupConfiguration;
            var configurationRoot = buildContext.ConfigurationRoot;
            var services          = buildContext.ServiceCollection;

            // Заменяем реализацию фабрики опций на свою.
            services.Add(ServiceDescriptor.Transient(typeof(IOptionsFactory <>), typeof(Configuration.OptionsFactory <>)));

            // Добавляем поддержку IOptions, IOptionsSnapshot, IOptionsMonitor
            services.AddOptions();

            // Logging
            services.RegisterLogging(buildContext.LoggerFactory);

            // Регистрируем строготипизированные конфигурации.
            services.RegisterConfigurationTypes(configurationRoot, buildContext.ExportedTypes, startupConfiguration);

            // Регистрируем типы по атрибуту [Register]
            services.RegisterWithRegisterAttribute(buildContext.ExportedTypes);

            // todo: зарегистрировать не исходные типы, а результирующий
            services.AddSingleton(buildContext.StartupConfiguration);
            services.AddSingleton(buildContext.StartupInfo);

            var modulesOptions = startupConfiguration.Modules;

            startupConfiguration.ConfigureModules(modulesOptions);

            // Регистрируем модули.
            List <Type> moduleTypes = new List <Type>();

            if (modulesOptions.AutoDiscoverModules)
            {
                moduleTypes = buildContext.ExportedTypes.GetClassTypesAssignableTo <IModule>().ToList();

                logger.LogInformation($"Found {moduleTypes.Count} modules:");
                foreach (var moduleType in moduleTypes)
                {
                    logger.LogInformation($"Autodiscovered module: {moduleType.Name}");
                }
            }

            var userDefinedModules = modulesOptions.ModuleTypes;

            if (userDefinedModules.Length > 0)
            {
                logger.LogInformation("UserDefinedModules modules:");
                foreach (var moduleType in userDefinedModules)
                {
                    logger.LogInformation($"UserDefined module: {moduleType.Name}");
                }
                moduleTypes.AddRange(userDefinedModules);
            }

            if (moduleTypes.Count > 0)
            {
                services.RegisterModules(moduleTypes);
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Конфигурирование сервисов.
        /// </summary>
        /// <param name="buildContext">Контекст построения приложения.</param>
        public void ConfigureServices(BuildContext buildContext)
        {
            var logger = buildContext.Logger;

            logger.LogInformation("ConfigureServices started");

            StartupConfiguration startupConfiguration = buildContext.StartupConfiguration;
            ILoggerFactory       loggerFactory        = buildContext.LoggerFactory;
            var configurationRoot = buildContext.ConfigurationRoot;
            var services          = buildContext.ServiceCollection;

            // Logging
            services.RegisterLogging(loggerFactory);

            // Регистрируем строготипизированные конфигурации.
            services.RegisterConfigurationTypes(configurationRoot, buildContext.ExportedTypes, startupConfiguration.Profile);

            // Регистрируем типы по атрибуту [Register]
            services.RegisterWithRegisterAttribute(buildContext.ExportedTypes);

            // todo: зарегистрировать не исходные типы, а результирующий
            services.AddSingleton(buildContext.StartupConfiguration);
            services.AddSingleton(buildContext.StartupInfo);

            var modulesOptions = startupConfiguration.Modules;

            startupConfiguration.ConfigureModules(modulesOptions);

            // Регистрируем модули.
            List <Type> moduleTypes = new List <Type>();

            if (modulesOptions.AutoDiscoverModules)
            {
                moduleTypes = buildContext.ExportedTypes.GetClassTypesAssignableTo <IModule>().ToList();

                logger.LogInformation($"Found {moduleTypes.Count} modules:");
                foreach (var moduleType in moduleTypes)
                {
                    logger.LogInformation($"Autodiscovered module: {moduleType.Name}");
                }
            }

            var userDefinedModules = modulesOptions.ModuleTypes;

            if (userDefinedModules.Length > 0)
            {
                logger.LogInformation("UserDefinedModules modules:");
                foreach (var moduleType in userDefinedModules)
                {
                    logger.LogInformation($"UserDefined module: {moduleType.Name}");
                }
                moduleTypes.AddRange(userDefinedModules);
            }

            if (moduleTypes.Count > 0)
            {
                services.RegisterModules(moduleTypes);
            }

            logger.LogInformation("ConfigureServices finished");
        }