Q:

Get value of a class property by JsonProperty

For environment settings, we are storing JSON blobs in our DB, such as:
[
  {
    "env": "local",
    "keya": "valueA_local"
    "keyb": "valueB_local"
  },
  {
    "env": "development",
    "keya": "valueA_dev"
    "keyb": "valueB_dev"
  },
  {
    "env": "qa",
    "keya": "valueA_qa"
    "keyb": "valueB_qa"
  }
]

And we have an enum:
public enum EnvironmentSettings
{
    KeyA = 1,
    KeyB = 2,
}

And we have a class:
[Serializable]
public class MyProjectEnvironmentSettings
{
    [JsonProperty("env")]
    public string Environment { get; set; }

    [JsonProperty("keya")]
    public string KeyA{ get; set; }

    [JsonProperty("keyb")]
    public string KeyB{ get; set; }
}

And finally, I need to create a method that returns a value for a given pair. I'd like this method to not have to be modified if a new setting is added.
public string GetEnvironmentSetting(EnvironmentSettings environmentSetting)
{
    List<MyProjectEnvironmentSettings> environmentSettings = //  get the entire list from the DB
    string envName = // get environment
    string keyToGet = environmentSetting.ToString().ToLower();

    // This will get the group of settings specific to the environment
    var envSettings = environmentSettings.Where(e => e.Environment.ToLower() == envName).FirstOrDefault();

    // And last, I need to get the value for the specific setting that is being requested 
    string settingValue = envSettings.Where(e => e.???? == keyToGet );  // <---------- This is where I need help!
}

I'm unsure of how to query by the properties JsonProperty attribute.
Thanks!

A:

You can use reflection.
var property = typeof(MyProjectEnvironmentSettings)
    .GetProperties()
    .FirstOrDefault(prop => prop
        .GetCustomAttribute<JsonPropertyAttribute>()?.PropertyName == keyToGet);
string settingValue = property?.GetValue(envSettings);

You may need to add BindingFlags if you change the accessibility of your properties.

This way you won't have to change your GetEnvironmentSetting method, but you will still need to update your enum and your class's  properties each time you add something.
Also, you will still have the burden of making sure the names match. You could also create a mapping between enum and properties (even directly to the PropertyInfo, so you could cache them), but that then creates a third thing that you have to maintain for each change.

