0

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!

Casey Crookston
  • 13,016
  • 24
  • 107
  • 193

1 Answers1

4

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.

Chronicle
  • 1,565
  • 3
  • 22
  • 28
  • I suspect that OP is asking "how to find a property by value of custom attribute" and not just "how to get property by name" - something like https://stackoverflow.com/questions/3289198/custom-attribute-on-property-getting-type-and-value-of-attributed-property and not https://stackoverflow.com/questions/5508050/how-to-get-a-property-value-based-on-the-name – Alexei Levenkov Apr 07 '20 at 21:34
  • Thanks! Testing. – Casey Crookston Apr 07 '20 at 21:47
  • @ `GetCustomAttribute` I am getting `The type 'System.Text.Json.JsonProperty' cannot be used as type parameter 'T' in the generic type or method 'CustomAttributeExtensions.GetCustomAttribute(MemberInfo)'. There is no boxing conversion from 'System.Text.Json.JsonProperty' to 'System.Attribute'.` – Casey Crookston Apr 07 '20 at 21:50
  • Yeah should be `JsonPropertyAttibute`. There may be some syntax errors since I typed it from memory. I fixed it in the answer @CaseyCrookston – Chronicle Apr 07 '20 at 21:52