Привязать netcore IConfigurationSection к динамическому объекту - PullRequest
0 голосов
/ 24 апреля 2018

В моем appSettings.json у меня есть раздел конфигурации, который может содержать что угодно, только если он действителен в json.Обычно это набор ключ / значение (строка / строка)

Я хотел бы получить его в своем коде и вернуть его при вызове контроллера.

Я посмотрел на источниккод (https://github.com/aspnet/Configuration/blob/6d9519622b5db2c5ac6bafa8bcdb25fe27914de3/src/Config.Binder/ConfigurationBinder.cs) и, кажется, я обречен с готовыми решениями.

Если я ограничу вариант использования парами ключ-значение, я могу использовать AsEnumerable () в IConfigSectionи это нормально.Если я хочу разрешить списки, тогда я все еще могу анализировать ключи для поиска: Number, но есть ли у кого-то способ легко десериализовать случайный объект?Или еще лучше получить раздел конфигурации без десериализации.

Например

{
 "mySettings": 
 {
   "key1": "value1",
   "key2": "value2",
   "list": [ "item1", "item2", "item3" ],
   "complexObject": {
     "key": "value",
     "anything" :  [{"id": "3", "name": "John"}]
   }
 }
}

1 Ответ

0 голосов
/ 24 апреля 2018

Это возможно, если вы злоупотребляете динамическими объектами .NET 4.Как вы сказали, вы можете перечислить все ключи в конфигурации, и все они следуют одному и тому же шаблону.В вашем примере все представляющие интерес ключи:

mySettings null 
mySettings:list null 
mySettings:list:2 item3 
mySettings:list:1 item2 
mySettings:list:0 item1 
mySettings:key3 value3 
mySettings:key2 value2 
mySettings:key1 value1 
mySettings:complexObject null 
mySettings:complexObject:key value 
mySettings:complexObject:anything null 
mySettings:complexObject:anything:0 null 
mySettings:complexObject:anything:0:name John 
mySettings:complexObject:anything:0:id 3 

Из этого мы можем построить ExpandoObject, например так:

[HttpGet]
public IActionResult Get([FromServices] IConfiguration config)
{
    var result = new ExpandoObject();

    // retrieve all keys from your settings
    var configs = config.AsEnumerable().Where(_ => _.Key.StartsWith("mySettings"));
    foreach(var kvp in configs) 
    {
        var parent = result as IDictionary<string, object>;
        var path = kvp.Key.Split(':');

        // create or retrieve the hierarchy (keep last path item for later)
        var i = 0;
        for (i = 0; i < path.Length - 1; i++)
        {
            if (!parent.ContainsKey(path[i]))
            {
                parent.Add(path[i], new ExpandoObject());
            }

            parent = parent[path[i]] as IDictionary<string, object>;
        }

        if (kvp.Value == null)
            continue;

        // add the value to the parent
        // note: in case of an array, key will be an integer and will be dealt with later
        var key = path[i];
        parent.Add(key, kvp.Value);
    }

    // at this stage, all arrays are seen as dictionaries with integer keys
    ReplaceWithArray(null, null, result);

    return Ok(result);
}

private void ReplaceWithArray(ExpandoObject parent, string key, ExpandoObject input) 
{
    if (input == null)
        return;

    var dict = input as IDictionary<string, object>;
    var keys = dict.Keys.ToArray();

    // it's an array if all keys are integers
    if (keys.All(k => int.TryParse(k, out var dummy))) {
        var array = new object[keys.Length];
        foreach(var kvp in dict) {
            array[int.Parse(kvp.Key)] = kvp.Value;
        }

        var parentDict = parent as IDictionary<string, object>;
        parentDict.Remove(key);
        parentDict.Add(key, array);
    }
    else
    {
        foreach (var childKey in dict.Keys.ToList())
        {
            ReplaceWithArray(input, childKey, dict[childKey] as ExpandoObject);
        }
    }
}

Примечание: начиная с двоеточия : используется в качестве разделителя, у вас не может быть ключа, который содержит двоеточие.

Наконец, поскольку теперь у вас есть динамический объект, вы можете напрямую получить его свойства:

dynamic asDym = result;
string name = asDym.mySettings.complexObject.anything[0].name;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...