YamlDotNet 根据值更改属性名称

时间:2021-01-18 18:00:49

标签: c# .net yaml yamldotnet

我正在尝试根据我在 yaml 文件的输出中获得的值来格式化对象的属性名称。我正在使用 yamldotnet 库。下面是我的课

State.cs

public class State
    {
        public string name { get; set; }
        public List<Operation> operations { get; set; }

    }

Operation.cs

public class Operation
    {
        public string name { get; set; }
        public string type { get; set; }
    }

在状态类中,我有操作列表。序列化后,我得到以下 yaml 输出:

states:
- name: uPError
  operations:
  - name: switch on uP
    type: entry
  - name: switch off uP
    type: exit
  - name: test Do
    type: do

但我打算显示的格式如下:

states:
- name: uPError
  entryActions: [switch on uP]
  exitActions: [switch off uP]
  doActions: [test Do]

我正在获取类型及其名称,根据类型,我需要将其更改为 entryActionexitActionsdoActions 和然后附加相应的名称。我怎样才能实现上述预期格式?提前致谢。

1 个答案:

答案 0 :(得分:0)

实现此目的的一种方法是实现 IYamlTypeConverter 以自定义 State 类型的转换。这使您可以控制类的整个序列化:

public class StateConverter : IYamlTypeConverter
{
    public bool Accepts(Type type)
    {
        return type == typeof(State);
    }

    public object? ReadYaml(IParser parser, Type type)
    {
        var state = new State { operations = new List<UserQuery.Operation>() };
        
        parser.Consume<MappingStart>();
        while (!parser.TryConsume<MappingEnd>(out var _))
        {
            var key = parser.Consume<Scalar>().Value;
            if (key == nameof(state.name))
            {
                state.name = parser.Consume<Scalar>().Value;
            }
            else
            {
                parser.Consume<SequenceStart>();
                while (!parser.TryConsume<SequenceEnd>(out var _))
                {
                    state.operations.Add(new Operation
                    {
                       type = key,
                       name = parser.Consume<Scalar>().Value,
                    });
                }
            }
        }
        
        return state;
    }

    public void WriteYaml(IEmitter emitter, object? value, Type type)
    {
        var state = (State)value!;
        
        emitter.Emit(new MappingStart());
        
        emitter.Emit(new Scalar(nameof(state.name)));
        emitter.Emit(new Scalar(state.name));

        foreach (var operationGroup in state.operations.GroupBy(o => o.type))
        {
            emitter.Emit(new Scalar(operationGroup.Key));

            emitter.Emit(new SequenceStart(null, null, false, SequenceStyle.Flow));
            foreach (var operation in operationGroup)
            {
                emitter.Emit(new Scalar(operation.name));
            }
            emitter.Emit(new SequenceEnd());
        }

        emitter.Emit(new MappingEnd());
    }
}

您需要在 SerializerBuilderDeserializerBuilder 上注册该类型:

var serializer = new SerializerBuilder()
    .WithTypeConverter(new StateConverter())
    .Build();
var deserializer = new DeserializerBuilder()
    .WithTypeConverter(new StateConverter())
    .Build();