Это возможно, если вы злоупотребляете динамическими объектами .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;