1
\$\begingroup\$

I'm pretty new to this so constructive criticism is acceptable. I'm trying to find any way I can improve this system, all it does is take a string, determine if that string is a web address or a file location, if its a web address, it will download the elements, if file then it loads the elements.

Pretty simple stuff, but is there any way I can improve here?

public class JsonConfigProvider : IConfigProvider
{
    private readonly ILogger _logger;
    private IDictionary<string, string> _elements;

    public JsonConfigProvider(
        ILogger logger,
        IDictionary<string, string> elements)
    {
        _logger = logger;
        _elements = elements;
    }

    public void Load(string fileLocation, WebClient webClient = null)
    {
        try
        {
            _elements = Uri.TryCreate(fileLocation, UriKind.Absolute, out var uri) ? DownloadElements(uri, webClient) : LoadElements(fileLocation);
        }
        catch (WebException)
        {
            _logger.Error($"Failed to download the config from web address: {fileLocation}");
        }
        catch (FileNotFoundException)
        {
            _logger.Error($"Failed to load config from file: {fileLocation}");
        }
        catch (Exception)
        {
            _logger.Error("Something went wrong, we couldn't load the config file.");
        }
    }

    private static IDictionary<string, string> DownloadElements(Uri uri, WebClient webClient)
    {
        if (webClient == null)
        {
            throw new WebException("webClient is null.");
        }

        var content = webClient.DownloadString(uri);
        return JObject.Parse(content).ToFlatDictionary(content);
    }

    private static IDictionary<string, string> LoadElements(string configFile)
    {
        var content = File.ReadAllText(configFile);
        return JObject.Parse(content).ToFlatDictionary(content);
    }

    public string this[string key] => _elements[key];

    public void Set(string key, string value, bool updateFile)
    {
        _elements[key] = value;
    }
}

Not really needed, but here is the ToFlatDictionary method.

public static Dictionary<string, string> ToFlatDictionary(this JToken token, string path = null)
{
    switch (token.Type)
    {
        case JTokenType.Object:
            return token.Children<JProperty>()
                .SelectMany(x => x.Value.ToFlatDictionary(x.Name))
                .ToDictionary(x => path == null ? x.Key : string.Join(".", path, x.Key), x => x.Value);

        case JTokenType.Array:
            return token
                .SelectMany((x, i) => x.ToFlatDictionary(i.ToString()))
                .ToDictionary(x => path == null ? x.Key : string.Join(".", path, x.Key), x => x.Value);

        default:
            return new Dictionary<string, string>
            {
                [path] = ((JValue)token).Value.ToString()
            };
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.