0

I have this MagicSgtrings class that holds some constants which I'm using in my worker service.

internal class MagicStrings
{
    public const string HttpClientName = "X_HttpClient";
  ...
}

usage: MagicStrings.HttpClientName

I also have those values set in appsettings.json, MagicStrings being used like fallback for configuration settings:

public Worker( IConfiguration config) => (_config) = (config){
...
   protected override async Task ExecuteAsync(CancellationToken stoppingToken)
   {
    ...
    var httpClient = _httpClientFactory.CreateClient(
        _config.GetValue<string>("HttpClientBasicConfig:HttpClientName")
        ?? MagicStrings.HttpClientName);
   }
}

What I would like is to have this _config.GetValue<string>("HttpClientBasicConfig:HttpClientName") ?? MagicStrings.HttpClientName) moved into MagicStrings class something like this:

internal class MagicStrings
{
    private readonly IConfiguration _config = null!;

    public MagicStrings(IConfiguration config) => (_config) = (config);

    public const string HttpClientName =
        _config.GetValue<string>("HttpClientBasicConfig:HttpClientName")
        ?? "X_HttpClient";
  or
    public static readonly string HttpClientName2 =
        _config.GetValue<string>("HttpClientBasicConfig:HttpClientName")
        ?? "X_HttpClient";
...

So I can used it like MagicStrings.HttpClientName in the entire app

3
  • It's not possible with const, unless you have some tool to update the value in code for each constant shortly before compile, and then any changes to the config won't be reflected once the application is compiled. Commented Feb 19 at 8:07
  • 2
    Anyway, it seems a trivial case of calling some code to initialize the values during application start up. I'm not really following what you're needing help with. Commented Feb 19 at 8:09
  • don't really know how to do it to achieve what I want, I tried to make private static IConfiguration _config and initialize the HttpClientName2 value in a static constructor but kind feels like not a good way to do it Commented Feb 19 at 8:44

2 Answers 2

3

@Ivan Petrov answer did the job, also his answer made me thing using options pattern with default values for fields which looks like this:

public class PVO_HttpClientBasicConfig
{
    public string HttpClientName { get; set; } = "PVO_HttpClient";
...
}

So if there is no key of HttpClientName in appsettgins.json it will use the default value from class definition -> this won't work for null values in appsettings.json

Sign up to request clarification or add additional context in comments.

1 Comment

This is the approach that came to mind when I read the question. Then I remembered that I did this exact things yesterday. It handles cases where the appsettings files do not call out a value for a config POCO, but does not override an empty string value - although an empty string might actually be what is desired in some cases.
1

I think it's more idiomatic to use AddInMemoryCollection:

builder.Configuration.AddInMemoryCollection(new Dictionary<string, string>
{
     {$"{nameof(HttpClientBasicConfig)}:{nameof(HttpClientBasicConfig.HttpClientName)}",MagicStrings.HttpClientName }
});

And then you need to re-add the defaults (other config that fit your case) which might be:

builder.Configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
       .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true, reloadOnChange: true);
builder.Configuration.AddEnvironmentVariables();

This way you will fall back on the MagicStrings constants whenever you haven't setup anything via appsettings/environment variables. So in your consuming code you won't need to make any checks and can use either IOptions<TOptions> or directly IConfiguration.

2 Comments

seeing the options pattern now, I'm thinking if my problem wouldn't be solved simply with default values for class fields when defining the class for options pattern => public string HttpClientName { get; set; } = "X_HttpCLient";
@sTx it could work - maybe look at this question/answer where this approach was suggested.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.