YamlDotNet:如何自定义反序列化器以处理具有不同类型值的相同密钥

时间:2018-07-20 05:07:22

标签: yaml yamldotnet

config.yaml:

App1:
  settings:
    redirectUrl: http://www.test.com
App2:
  settings:
    redirectUrl:
      test: http://www.test.com
      prod: http://www.prod.com

C#对象

public class Config
 {
    public Dictionary<string, App> Apps { get; set; }
 }

public class App
 {
    public Dictionary<string, Setting> Settings { get; set; }
 }

public class Setting
 {
    public string Test {get;set;}
    public string Prod {get;set;}
 }

预期结果:

对于App1testprod都是相同的http://www.test.com

对于App2testhttp://www.test.com,而prodhttp://www.prod.com

我已经做了大量研究,但是无法弄清楚如何使用自定义解串器来实现这一目标。 请帮忙。

1 个答案:

答案 0 :(得分:1)

您可以使您的Settings类实现IYamlConvertible。该界面允许您控制序列化过程。可能的实现方式可能是:

public class SettingsBase
{
    public string Test { get; set; }
    public string Prod { get; set; }
}

public class Setting : SettingsBase, IYamlConvertible
{
    public void Read(IParser parser, Type type, ObjectDeserializer nestedObjectDeserializer)
    {
        var scalar = parser.Allow<Scalar>();
        if (scalar != null)
        {
            Test = Prod = scalar.Value;
        }
        else
        {
            var values = (SettingsBase)nestedObjectDeserializer(typeof(SettingsBase));
            this.Test = values.Test;
            this.Prod = values.Prod;
        }
    }

    public void Write(IEmitter emitter, ObjectSerializer nestedObjectSerializer)
    {
        if (Test == Prod)
        {
            nestedObjectSerializer(Test);
        }
        else
        {
            nestedObjectSerializer(new SettingsBase { Test = this.Test, Prod = this.Prod });
        }
    }
}

在这里,我使用基类(SettingsBase)作为轻松(反)序列化属性的方法,但是可以使用另一种策略。基本上,Read方法检查当前标记是否为标量。如果是这样,它将使用其值。否则,它将反序列化为SettingsBaseWrite方法则相反。

A fully working example is available here