Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access to configuration without dependency injection

Tags:

c#

.net-core

I was wondering if there was a way to access Configuration (Microsoft.Extensions.Configuration) without the use of dependency injection. Only examples I see are through constructor injection (using IOptions or injecting Configuration directly).

My dilemma is that I have a utility class-- not a service-- that has static methods to do things on the fly. In a few of those static methods I would like to retrieve a couple of properties from appsettings.json dynamically. Since this is strictly a utility class, I don't want have to inject this class into every other class that needs to use a method or two from the utility.

Any ideas on how to access the properties of appsettings.json without some sort of dependency injection.

FYI: using c# and .net core 1.1

like image 502
Los Morales Avatar asked Jan 20 '17 20:01

Los Morales


3 Answers

Wow, what a lot of comments, why don't people answer the question instead of telling someone they don't want to do what they obviously do. Anyway, hopefully this will keep both camps satisfied.

If you take a standard AppSettings class with a single public constructor that takes an IConfiguration that can be used to populate all the AppSettings properties, this keeps the ability for Dependency Injection.

If at the end of the constructor we set a static property 'Current' pointing to the current instance of AppSettings, this will allow us access to the settings from that point onwards via the static property without the need for further injection.

If we now create a static Default 'GetCurrentSettings' method to get the settings from a json file, this can be used as a default instantiation, so that if 'Current' is called and is set to null, we just go off and populate the settings from the file. Here's an example of what I mean...

public class AppSettings
{
    private static AppSettings _appSettings;

    public string AppConnection { get; set; }

    public AppSettings(IConfiguration config)
    {
        this.AppConnection = config.GetValue<string>("AppConnection");

        // Now set Current
        _appSettings = this;
    }

    public static AppSettings Current
    {
        get
        {
            if(_appSettings == null)
            {
                _appSettings = GetCurrentSettings();
            }

            return _appSettings;
        }
    }

    public static AppSettings GetCurrentSettings()
    {
        var builder = new ConfigurationBuilder()
                        .SetBasePath(Directory.GetCurrentDirectory())
                        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                        .AddEnvironmentVariables();

        IConfigurationRoot configuration = builder.Build();

        var settings = new AppSettings(configuration.GetSection("AppSettings"));

        return settings;
    }
}

So from this you would be able to call anywhere in code AppSettings.Current.AppConnection

If it's been instantiated using DI the injected version would be retrieved otherwise the default version would be taken from an appsettings.json file. I doubt it satisfies everyone and I'm not sure I've explained it very well, but hopefully it makes sense.

like image 179
Hoots Avatar answered Nov 15 '22 12:11

Hoots


I just made the config property in Startup static:

public static IConfiguration Configuration { get; set; }

Now I can access it anywhere in the application with just Startup.Configuration.

like image 30
ProfK Avatar answered Nov 15 '22 14:11

ProfK


I am totally agree with solution suggested by @Hoot but i have modified class little. i have modified class because i need to pass dynamic Key to fetch value for same..

Configuration Class :

public class ConfigHelper
    {

        private static ConfigHelper _appSettings;

        public string appSettingValue { get; set; }

        public static string AppSetting(string Key)
        {
          _appSettings = GetCurrentSettings(Key);
          return _appSettings.appSettingValue;
        }

        public ConfigHelper(IConfiguration config, string Key)
        {
            this.appSettingValue = config.GetValue<string>(Key);
        }

        public static ConfigHelper GetCurrentSettings(string Key)
        {
            var builder = new ConfigurationBuilder()
                            .SetBasePath(Directory.GetCurrentDirectory())
                            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                            .AddEnvironmentVariables();

            IConfigurationRoot configuration = builder.Build();

            var settings = new ConfigHelper(configuration.GetSection("AppSettings"), Key);

            return settings;
        }
    }

Appsettings.Json Configuration:

 "AppSettings": {
    "WebApplicationUrl": "http://localhost:0000/",
    "ServiceUrl": "http://localhost:0000/",
    "CommonServiceUrl": "http://localhost:0000/"
  }

Calling Example:

string ServiceUrl = ConfigHelper.AppSetting("ServiceUrl");

So from now we are able to pass dynamic key.

like image 5
Ankit Mori Avatar answered Nov 15 '22 14:11

Ankit Mori