Access to configuration without dependency injecti

2020-05-21 08:34发布

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

标签: c# .net-core
4条回答
ゆ 、 Hurt°
2楼-- · 2020-05-21 09:19

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.

查看更多
Melony?
3楼-- · 2020-05-21 09:20

I have a utility class-- not a service-- that has static methods

This is really the heart of your issue. You have static methods with dependencies, which is not DI-friendly.

I would argue that you have a good candidate for a service that you have made into a utility class. As a result of doing this, you have robbed yourself from being able to use DI properly. Either make the class an instance class or extract the applicable functionality into a service and you will have an avenue in which to inject your IOptions dependency.

You should avoid static classes/methods for anything that has (or is likely to have) dependencies.

查看更多
▲ chillily
4楼-- · 2020-05-21 09:25

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.

查看更多
贪生不怕死
5楼-- · 2020-05-21 09:28

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.

查看更多
登录 后发表回答