我可以按顺序读取 YamlDotNet 映射吗?

And*_*dre 2 .net yaml yamldotnet

是否可以按照它们在源文档中出现的相同顺序访问映射的键?即如果我有这个简单的文件:

values:
    first: something1
    second: something2
    third: something3
Run Code Online (Sandbox Code Playgroud)

然后我将能够以原始顺序获得一系列键:[第一,第二,第三]?

Ant*_*bry 5

实现此目的的一种方法是使用RepresentationModelAPI。它允许获得与底层结构紧密匹配的 YAML 文档的表示:

var stream = new YamlStream();
stream.Load(new StringReader(yaml));

var document = stream.Documents.First();

var rootMapping = (YamlMappingNode)document.RootNode;
var valuesMapping = (YamlMappingNode)rootMapping.Children[new YamlScalarNode("values")];

foreach(var tuple in valuesMapping.Children)
{
    Console.WriteLine("{0} => {1}", tuple.Key, tuple.Value);
}
Run Code Online (Sandbox Code Playgroud)

这种方法的缺点是您需要“手动”解析文档。另一种方法是使用序列化,并使用保留排序的类型。我不知道有任何现成的实现IDictionary<TKey, TValue>具有此特性,但如果您不关心高性能,实现起来相当简单:

// NB: This is a minimal implementation that is intended for demonstration purposes.
//     Most of the methods are not implemented, and the ones that are are not efficient.
public class OrderPreservingDictionary<TKey, TValue>
    : List<KeyValuePair<TKey, TValue>>, IDictionary<TKey, TValue>
{
    public void Add(TKey key, TValue value)
    {
        Add(new KeyValuePair<TKey, TValue>(key, value));
    }

    public bool ContainsKey(TKey key)
    {
        throw new NotImplementedException();
    }

    public ICollection<TKey> Keys
    {
        get { throw new NotImplementedException(); }
    }

    public bool Remove(TKey key)
    {
        throw new NotImplementedException();
    }

    public bool TryGetValue(TKey key, out TValue value)
    {
        throw new NotImplementedException();
    }

    public ICollection<TValue> Values
    {
        get { throw new NotImplementedException(); }
    }

    public TValue this[TKey key]
    {
        get
        {
            return this.First(e => e.Key.Equals(key)).Value;
        }
        set
        {
            Add(key, value);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

一旦你有了这样的容器,你就可以利用SerializationAPI 来解析文档:

var deserializer = new Deserializer();
var result = deserializer.Deserialize<Dictionary<string, OrderPreservingDictionary<string, string>>>(new StringReader(yaml));

foreach(var tuple in result["values"])
{
    Console.WriteLine("{0} => {1}", tuple.Key, tuple.Value);
}
Run Code Online (Sandbox Code Playgroud)

你可以在这个小提琴中看到一个完整的例子