<commit_before>﻿using Autofac;
using Autofac.Core;
using Microsoft.Extensions.Configuration;
using NetFusion.Base.Validation;
using NetFusion.Bootstrap.Plugins;
using NetFusion.Common.Extensions.Reflection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace NetFusion.Settings.Modules
{
    /// <summary>
    /// Provides loading and initializing of application settings when they are dependency injected into a 
    /// dependent component for the first time.  This plug-in module delegates to the Microsoft Extension
    /// Configuration implementation and loads a setting from its associated section.
    /// </summary>
    public class AppSettingsModule : PluginModule
    {
        public override void ScanAllOtherPlugins(TypeRegistration registration)
        {
            // Register all setting classes contained in all of the plug-ins
            // and when dependency injected, populates the settings by calling
            // the configuration implementation. 
            registration.PluginTypes.AssignableTo<IAppSettings>()
                .AsSelf()
                .InstancePerLifetimeScope()
                .OnActivating(LoadConfiguration);
        }

        private void LoadConfiguration(IActivatingEventArgs<object> handler)
        {
            var settings = handler.Instance;
            var sectionName = GetSettingsTypeSectionName(settings.GetType());

            if (sectionName != null)
            {
                // Lookup settings with the specified section name.  IConfiguration
                // is a service provided by MS Configuration Extensions.
                var configuration = handler.Context.Resolve<IConfiguration>();
                var section = configuration.GetSection(sectionName);

                // Bind the configuration to the settings instance.
                section.Bind(settings);
            }

            // Determine if the settings object can be validated.  Note:  The validation implementation
            // is being directly created and not using the host specified implementation so all settings
            // can be consistently validated.  But all other application validation delegates to the 
            // host specified implementation.
            var validator = new MSObjectValidator(settings);
            var result = validator.Validate();
            
            result.ThrowIfInvalid();
        }

        // Navigates up the settings base types and looks for all ConfigurationSection attributes
        // to build the full path of the settings location.
        private string GetSettingsTypeSectionName(Type settingsType)
        {
            var sectionNames = GetSectionNames(settingsType);
            return string.Join(":", sectionNames.Reverse().ToArray());
        }<commit_msg>Improved logging of invalid MS loaded configurations.<commit_after>﻿using Autofac;
using Autofac.Core;
using Microsoft.Extensions.Configuration;
using NetFusion.Base.Validation;
using NetFusion.Bootstrap.Logging;
using NetFusion.Bootstrap.Plugins;
using NetFusion.Common.Extensions.Reflection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace NetFusion.Settings.Modules
{
    /// <summary>
    /// Provides loading and initializing of application settings when they are dependency injected into a 
    /// dependent component for the first time.  This plug-in module delegates to the Microsoft Extension
    /// Configuration implementation and loads a setting from its associated section.
    /// </summary>
    public class AppSettingsModule : PluginModule
    {
        public override void ScanAllOtherPlugins(TypeRegistration registration)
        {
            // Register all setting classes contained in all of the plug-ins
            // and when dependency injected, populates the settings by calling
            // the configuration implementation. 
            registration.PluginTypes.AssignableTo<IAppSettings>()
                .AsSelf()
                .InstancePerLifetimeScope()
                .OnActivating(LoadConfiguration);
        }

        private void LoadConfiguration(IActivatingEventArgs<object> handler)
        {
            var settings = handler.Instance;
            var sectionName = GetSettingsTypeSectionName(settings.GetType());

            if (sectionName != null)
            {
                // Lookup settings with the specified section name.  IConfiguration
                // is a service provided by MS Configuration Extensions.
                var configuration = handler.Context.Resolve<IConfiguration>();
                var section = configuration.GetSection(sectionName);

                // Bind the configuration to the settings instance.
                section.Bind(settings);
            }

            // Determine if the settings object can be validated.  Note:  The validation implementation
            // is being directly created and not using the host specified implementation so all settings
            // can be consistently validated.  But all other application validation delegates to the 
            // host specified implementation.
            var validator = new MSObjectValidator(settings);
            var result = validator.Validate();

            if (result.IsInvalid)
            {
                Context.Logger.LogErrorDetails(
                    $"Invalid application setting: {settings.GetType().FullName}. With section name: {sectionName}.", 
                    result.ObjectValidations);
            }
            
            result.ThrowIfInvalid();
        }

        // Navigates up the settings base types and looks for all ConfigurationSection attributes
        // to build the full path of the settings location.
        private string GetSettingsTypeSectionName(Type settingsType)
        {
            var sectionNames = GetSectionNames(settingsType);
            return string.Join(":", sectionNames.Reverse().ToArray());
        }
{'fraction_non_alphanumeric': 0.06663343303423064, 'fraction_numerical': 0.0, 'mean_word_length': 2.3217439293598234, 'pattern_counts': {'":': 2, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1459118', 'n_tokens_mistral': 1315, 'n_tokens_neox': 1265, 'n_words': 460}