Выпуск сериализации типа тегов от YamlStream - PullRequest
1 голос
/ 04 июня 2019

У меня проблема с созданием файла конфигурации для класса, который включает список объектов, реализующих тот же интерфейс, когда я использую API YamlStream.

Я хочу сохранить локальные теги, которые я поместил в элементы списка, чтобы их можно было правильно десериализовать из другого контекста. В моем реальном проекте мне необходимо выполнить некоторую предварительную обработку узлов YamlNode. Однако, когда я хочу сериализовать YamlDocument в файл, теги локального типа теряются. Я вижу, что теги анализируются при преобразовании в YamlStream (для некоторых узлов свойство Tag установлено соответствующим образом). Однако после обработки они сериализуются без тегов.

У меня есть несколько примеров того, что я попробовал в этом репо: https://github.com/mariotee/YamlDotNetIssue

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

//pre processing would go here

using (var wr = new StringWriter())
{
    stream.Save(wr, false);
    File.WriteAllText("path", wr.ToString());
}

ожидаемый результат:

pets:  
- !Cat
  name: skippy
  likesMilk: true
- !Cat
  name: felix
  likesMilk: true
- !Dog
  name: ralf
  likesBones: true
- !Hamster
  name: Hamtaro
  likesTv: true
...

фактический результат:

pets:
- name: skippy
  likesMilk: true
- name: felix
  likesMilk: true
- name: ralf
  likesBones: true
- name: Hamtaro
  likesTv: true
...

1 Ответ

1 голос
/ 05 июня 2019

Как я уже прокомментировал, это ошибка. Однако вы можете обойти это, предоставив собственную реализацию IEmitter и принудительно установив для свойства IsImplicit класса MappingStart значение false:

public static void Main()
{
    var yaml = @"
pets:  
- !Cat
  name: skippy
  likesMilk: true
- !Cat
  name: felix
  likesMilk: true
- !Dog
  name: ralf
  likesBones: true
- !Hamster
  name: Hamtaro
  likesTv: true
...
";

    var stream = new YamlStream();
    stream.Load(new StringReader(yaml));
    stream.Save(new MappingFix(new Emitter(Console.Out)), false);
}

public class MappingFix : IEmitter
{
    private readonly IEmitter next;

    public MappingFix(IEmitter next)
    {
        this.next = next;
    }

    public void Emit(ParsingEvent @event)
    {
        var mapping = @event as MappingStart;
        if (mapping != null) {
            @event = new MappingStart(mapping.Anchor, mapping.Tag, false, mapping.Style, mapping.Start, mapping.End);
        }
        next.Emit(@event);
    }
}

Это дает ожидаемый результат:

pets:
- !Cat
  name: skippy
  likesMilk: true
- !Cat
  name: felix
  likesMilk: true
- !Dog
  name: ralf
  likesBones: true
- !Hamster
  name: Hamtaro
  likesTv: true
...

Обратите внимание, что для этого требуется последняя версия - YamlDotNet 6.1.1

...