简体   繁体   中英

Creating a static settings class in .net core class library

I am inviting criticism and feedback. A roast if you will. What I have done here feels wrong and I want to know why.

To create a static settings class in .net core that can returns settings from the appsettings.json file. It does work but it uses ConfigurationBuilder on every accessing of settings.

public static class GeneralSettings
{
    private static IConfigurationRoot Configuration = StartConfig();

    private static IConfigurationRoot StartConfig()
    {
        var configBuilder = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{environment}.json", optional: true, reloadOnChange: true)
            .AddEnvironmentVariables();

        return configBuilder.Build();
    }

    public static string ContextUserID
    {
        get
        {
            string result = 
                Configuration.GetSection("AppSettings").GetSection("ContextUserID").Value;

            return result;
        }
    }
}

Given the above code, you're rebuilding the configuration every time its called. You may as well make it a singleton. And since singletons are bad, well something else is probably wrong. Your instinct this feels wrong is RIGHT!

  1. Avoid static classes until you know they are static.
  2. Usually, common 'helper' classes like this violate one or more SOLID principles. (This is probably why you have that feel of the code being 'wrong')

Read more on how 'helper' classes like this do not adhere to SOLID principles, and what those principles are in this blog article

If instead of a static class, were you to leverage .NET Core's built in dependency injection, we could easily turn this abstraction into a bit of code that adheres to SOLID principles. That of course doesn't solve your problem of being able to use your new IContextSettings in another static class, but does enable you to use this interface as a first class citizen directly where you need the ContextUserID , and you would simply use dependency injection in your Controller , or PageModel

public interface IContextSettings
{
    string ContextUserID { get; }
}

public class ContextSettings : IContextSettings
{
    private IConfiguration configuration;

    public ContextSettings(IConfiguration configuration)
    {
        this.configuration = configuration;
    }
    public string ContextUserID => configuration.GetSection("AppSettings").GetSection("ContextUserID").Value;
}

Usage (RazorPages Example)

public class IndexModel : PageModel
{
    private readonly IContextSettings settings;

    public IndexModel(IContextSettings settings)
    {
        this.settings = settings;
    }
    public IActionResult OnGet()
    {
        var userId = settings.ContextUserID;
        return Page();
    }
}

Feels right... right?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM