Search code examples
c#configuration.net-6.0.net-standard-2.0configurationmanager

Analog of ConfigurationManager in dotnet 6 and netstandard 2.0, and Protected Section


In the .net framework, we've used to use either web.config or app.config with ConfigurationManager or WebConfigurationManager to read the configuration sections.

2 items stood out:

a) standard configuration file (XML) was loaded by framework. So when you call ConfigurationManager from ANY DLL in your application assemblies you get the section or appSettings that routed through Application Domain.

b) There was ability to have protected sections, i.e. you put some open text data and when application runs, this data will be encrypted.

Now, in .net 6 we have plenty of talk about new configuration manager -Microsoft.Extensions.Configuration.ConfigurationManager.

At first .net core came without it but Microsoft soon added back System.Configuration.ConfigurationManager, now available for net6.0 and netstandard2.0

I have found ZERO information on how to use Microsoft.Extensions.Configuration.ConfigurationManager directly from a class library. It is all seem to be designed for endpoint application, the executing assembly.

I seem understand that if you really want something like this, there are ways of doing it but all of it seem to be overly convoluted and directly related to ASP.NET CORE. And in the end, does not solve the main issue - how to deal with these protected configs from a DLL. For example, in my architecture, the EF stuff is located 2 levels down from the endpoint app. I don't want to pass connection string down below. I want my EF layer to be able by itself find encrypted connection, independently, if it is invoked from a console app, test project or Win Forms.

Are there any guidance to all these things outside the usual - "we now have this class in asp.net core"??


Solution

  • I came to this solution to achieve this functionality. It utilizes Singleton pattern to make this happen. And again, this is a prototype. 3 Projects

    1. Configuration library, contains the following code for singleton. This code loads settings in any way you want.
    public class ConfigSingleton
    {
        private static ConfigSingleton _instance;
    
    
        static ConfigSingleton()
        {
            _instance = new ConfigSingleton();
            _instance.Init();
        }
    
    
        public  static ConfigSingleton Instance { get { return _instance; } }
        public string StringSetting { get; private set; }
        public int IntSetting { get; private set; }
        public bool BoolSetting { get; private set; }
        public int InstanceId { get; private set; }
    
        private void Init()
        {
            IConfiguration Configuration = new msc.ConfigurationBuilder()
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile("appsettings.development.json", optional: true, reloadOnChange: true)
                .AddEnvironmentVariables() 
                //.AddUserSecrets("bbbb",)
                
                //.AddCommandLine(args)
                .Build();
                
            var section = Configuration.GetSection("CustomSettingsSection");
            StringSetting = section.GetValue<string>("StringSetting");
            IntSetting = section.GetValue<int>("NumericSetting");
            BoolSetting = section.GetValue<bool>("BoolSetting");
            InstanceId = Guid.NewGuid().ToString().GetHashCode();
        }
    
    }
    
    1. Consuming library. Things are simple here
    public static class ConfigWrapper
    {
        public static ConfigSingleton GetConfig()
        {
            return ConfigSingleton.Instance;
        }
    }
    
    1. Consuming console app, which consumes both libraries above and proves that we have same singleton object loaded with our settings
    public static void Main(string[] args)
    {
        Console.WriteLine("wrapper config id: " + netstandard20.lib.ConfigWrapper.GetConfig().InstanceId);
    
        var boolSet = netstandard20.lib.ConfigWrapper.GetConfig().BoolSetting;
        Console.WriteLine("Bool from wrapper: " + boolSet);
    
        var intSet = netstandard20.lib.ConfigWrapper.GetConfig().IntSetting;
        Console.WriteLine("int from wrapper: " + intSet);
    
        var strSet = netstandard20.lib.ConfigWrapper.GetConfig().StringSetting;
        Console.WriteLine("string from wrapper: " + strSet);
    
        Console.WriteLine("= = = = = = = = = = = = = = = = = = = = = =");
    
        Console.WriteLine("config id: " + netstandard20.lib.config.ConfigSingleton.Instance.InstanceId);
    
        boolSet = netstandard20.lib.config.ConfigSingleton.Instance.BoolSetting;
        Console.WriteLine("Bool from config: " + boolSet);
    
        intSet = netstandard20.lib.config.ConfigSingleton.Instance.IntSetting;
        Console.WriteLine("int from config: " + intSet);
    
        strSet = netstandard20.lib.config.ConfigSingleton.Instance.StringSetting;
        Console.WriteLine("string from config: " + strSet);
    
        Console.Read();
    }
    

    This works. Not sure if this is a "great idea"