3

YamlDotNet を使用して単純な構成ファイルを解析しています (深いネストなどはありません)。デシリアライザーは、重複するフィールドを含む文字列を解析し、以前の値を上書きします。例えば、

foo: bar
foo: baz

と同等と見なされます

foo: baz

私のアプリケーションでは、そのような重複によって例外がスローされることを望みます。これは可能ですか?

4

3 に答える 3

3

このUniqueKeysDictionary例は私にはうまくいきませんでした.2番目の例から、正確に検証する方法が明確ではありませんでした. しかし、重複が許可されておらず、ファイルを2回ロードしても問題ない場合は、はるかに簡単な方法を見つけました。

    private T DeserializeAndValidate<T>(StreamReader reader)
    {
        var yaml = new YamlStream();
        yaml.Load(reader); // throws if duplicates are found

        reader.BaseStream.Seek(0, SeekOrigin.Begin);
        using (var reader2 = new StreamReader(reader.BaseStream))
        {
            var deserializer = new Deserializer();
            var data = deserializer.Deserialize<T>(reader2);
            return data;
        }
    }
于 2018-11-23T11:00:33.820 に答える
1

リンターを含む解決策がありますが、YamlDotNet で例外がスローされることはないため、それがあなたに関連するかどうかはわかりません。の実装を置き換えることを避けることができるので、とにかく投稿します GenericDictionaryNodeDeserializer

これはyamllintコマンドライン ツールです。

sudo pip install yamllint

具体的には、key-duplicates重複したキーを検出するルールがあります。

$ cat test.yml
foo: bar
foo: baz

$ yamllint test.yml
test.yml
  2:1       error    duplication of key "foo" in mapping  (key-duplicates)
于 2016-02-02T10:38:45.607 に答える
1

デフォルトのノード デシリアライザーは、インデクサーを使用して値を割り当てます。目的の動作を実現する 1 つの方法は、次のように値の重複を許可しない型に逆シリアル化することです。

public class UniqueKeysDictionary<TKey, TValue>
    : Dictionary<TKey, TValue>
    , IDictionary<TKey, TValue>
{
    TValue IDictionary<TKey, TValue>.this[TKey key]
    {
        get { return base[key]; }
        set { base.Add(key, value); }
    }
}

完全に機能する例は、ここにあります

このソリューションの重大な問題の 1 つは、インデクサーのコントラクトに違反していることです。インデクサーの動作は、値を上書きする必要があります。

もう 1 つのアプローチは、 の実装を、インデクサーの代わりにメソッドGenericDictionaryNodeDeserializerを使用するものに置き換えることです。これは、ノード デシリアライザーを置き換える方法を示す別の例Add()の関連部分です。

var deserializer = new Deserializer();

var objectDeserializer = deserializer.NodeDeserializers
    .Select((d, i) => new {
        Deserializer = d as ObjectNodeDeserializer,
        Index = i
    })
    .First(d => d.Deserializer != null);

deserializer.NodeDeserializers[objectDeserializer.Index] =
    new ValidatingNodeDeserializer(objectDeserializer.Deserializer);
于 2015-06-02T12:58:03.557 に答える