我不在方括号内,但如果有任何兴趣,我确实有一些扩展方法。
他们可以无休止地遍历并获取一个对象或在字典键链的末尾设置一个通用值。 Get() 返回一个对象,但如果需要,它很容易修复为泛型类型。
由于键是基于参数的,如果您有一个非常动态的环境,您可以放入一个动态的键数组。
像这样工作:
var exists1 = info.Exists("Gen", "name", "One key too much"); // false
var exists2 = info.Exists("Gen", "chapters"); // true
var value1 = info.Get("Gen", "name", "One key too much"); // null
var value2 = info.Get("Gen", "chapters"); // "50"
var valueToSet = "myNewValue";
var successSet1 = info.TrySet(valueToSet, "Gen", "before", "One key too much"); // false
var successSet2 = info.TrySet(valueToSet, "Gen", "after"); // true | "Gen" -> "after" set to "myNewValue"
var dictionary1 = info.FindSubDictionary("Gen", "name", "One key too much"); // null
var dictionary2 = info.FindSubDictionary("Gen", "chapters"); // "Gen" sub dictionary
我没有对它进行太多测试,也没有考虑过它应该在什么时候返回,但是如果你觉得它有用,它可能是开始修补的东西。
4 种扩展方法主要协同工作,提供 Exists、Get、TrySet 和 (应该是什么) 一个内部方法来解析字典树。
TrySet:
/// <summary>
/// Tries to set a value to any dictionary found at the end of the params keys, or returns false
/// </summary>
public static bool TrySet<T>(this System.Collections.IDictionary dictionary, T value, params string[] keys)
{
// Get the deepest sub dictionary, set if available
var subDictionary = dictionary.FindSubDictionary(keys);
if (subDictionary == null) return false;
subDictionary[keys.Last()] = value;
return true;
}
获取:
/// <summary>
/// Returns a value from the last key, assuming there is a dictionary available for every key but last
/// </summary>
public static object Get(this System.Collections.IDictionary dictionary, params string[] keys)
{
var subDictionary = dictionary.FindSubDictionary(keys);
if (subDictionary == null) return null; // Or throw
return subDictionary[keys.Last()];
}
存在:
/// <summary>
/// Returns whether the param list of keys has dictionaries all the way down to the final key
/// </summary>
public static bool Exists(this System.Collections.IDictionary dictionary, params string[] keys)
{
// If we have no keys, we have traversed all the keys, and should have dictionaries all the way down.
// (needs a fix for initial empty key params though)
if (keys.Count() == 0) return true;
// If the dictionary contains the first key in the param list, and the value is another dictionary,
// return that dictionary with first key removed (recursing down)
if (dictionary.Contains(keys.First()) && dictionary[keys.First()] is System.Collections.IDictionary subDictionary)
return subDictionary.Exists(keys.Skip(1).ToArray());
// If we didn't have a dictionary, but we have multiple keys left, there are not enough dictionaries for all keys
if (keys.Count() > 1) return false;
// If we get here, we have 1 key, and we have a dictionary, we simply check whether the last value exists,
// thus completing our recursion
return dictionary.Contains(keys.First());
}
查找子字典:
/// <summary>
/// Returns the possible dictionary that exists for all keys but last. (should eventually be set to private)
/// </summary>
public static System.Collections.IDictionary FindSubDictionary(this System.Collections.IDictionary dictionary, params string[] keys)
{
// If it doesn't exist, don't bother
if (!dictionary.Exists(keys)) return null; // Or throw
// If we reached end of keys, or got 0 keys, return
if (keys.Count() == 0) return null; // Or throw
// Look in the current dictionary if the first key is another dictionary.
return dictionary[keys.First()] is System.Collections.IDictionary subDictionary
? subDictionary.FindSubDictionary(keys.Skip(1).ToArray()) // If it is, follow the subdictionary down after removing the key just used
: keys.Count() == 1 // If we only have one key remaining, the last key should be for a value in the current dictionary.
? dictionary // Return the current dictionary as it's the proper last one
: null; // (or throw). If we didn't find a dictionary and we have remaining keys, the dictionary tree is invalid
}
编辑:
注意到您需要 CSV 密钥。从上面构建应该很容易,但我使用单个 csv-key 和一个额外的可选自定义分隔符做了一个简单的示例。
var csvResult1 = info.Get("Gen, chapters, One key too much"); // null
var csvResult2 = info.Get("Gen, chapters"); // "50"
// With custom separator
var csvResult3 = info.Get("Gen;chapters;One key too much", separator: ";");
var csvResult4 = info.Get("Gen; chapters", separator: ";");
代码:
/// <summary>
/// Returns a value from the last key of a csv string with keys, assuming there is a dictionary available for every key but the last.
/// </summary>
public static object Get(this System.Collections.IDictionary dictionary, string csvKeys, string separator = ",")
{
if (String.IsNullOrEmpty(csvKeys)) throw new ArgumentNullException("Csv key input parameters is not allowed to be null or empty", nameof(csvKeys));
var keys = csvKeys.Split(separator).Select(k => k.Trim());
var subDictionary = dictionary.FindSubDictionary(keys.ToArray());
if (subDictionary == null) return null; // Or throw
return subDictionary[keys.Last()];
}
不过,你最好测试最后一个,我没有运行它。不过应该可以正常运行...我只是不能保证它会:)