我有一个第三方YAML数据,我需要对它们进行反序列化修改,然后进行序列化并发回。问题在于它们的数据已格式化,因此每个条目都是其自己的序列。我能够提出一种可以对数据进行序列化的类型转换器,但是在为此编写序列化程序之前,我想看看是否有更好的方法可以解决此问题。
YAML:
---
Message:
- Name: GENCBL
- Style: 1x7 Western Fixed
- PrintDelay: 0
- PrintCount: 90
- Orientation:
- Rotation: 0
- HFlip: False
- VFlip: False
- Printer:
- Type: 8900
- Pitch:
- Horizontal: 320
- VerticalAdj: 0
- Line:
- Field:
- Name: Field 1
- Type: Text
- Visibility: True
- Rotation: 0
- Negative: False
- Locale: en_GB
- Boldness: 1
- Pos:
- X: 25
- Y: 0
- Font:
- Name: Universal
- Size: 7
- Units: Drops
- Rotation: 0
- Parameters:
- Text: FEET
- Field:
- Name: Field 1
- Type: Text
- Visibility: True
- Rotation: 0
- Negative: False
- Locale: en_GB
- Boldness: 1
- Pos:
- X: 502
- Y: 0
- Font:
- Name: Universal
- Size: 7
- Units: Drops
- Rotation: 0
- Parameters:
- Text: ---
- Field:
- Name: Field 1
- Type: Date
- Visibility: True
- Rotation: 0
- Negative: False
- Locale: en_GB
- Boldness: 1
- Pos:
- X: 968
- Y: 0
- Font:
- Name: Universal
- Size: 7
- Units: Drops
- Rotation: 0
- Parameters:
- Format: ""%MM%""
- Offset:
- Time: 0:0
...
TypeConverter:
public class SequenceConverter<T> : IYamlTypeConverter where T: new()
{
/// <summary>
/// Gets a value indicating whether the current converter supports converting the specified type.
/// </summary>
public bool Accepts(Type type)
{
return typeof(T).IsAssignableFrom(type);
}
/// <summary>Reads an object's state from a YAML parser.</summary>
public object ReadYaml(IParser parser, Type type)
{
var baseObject = new T();
parser.Consume<SequenceStart>();
while (parser.Current is MappingStart)
{
ParseNextField(parser, baseObject);
}
parser.Consume<SequenceEnd>();
return baseObject;
}
private static void ParseNextField(IParser parser, object current)
{
parser.Consume<MappingStart>();
Scalar key = parser.Consume<Scalar>();
var keyValue = key.Value;
if (keyValue == "Offset")
{
keyValue = parser.Current is Scalar ? "OffsetString" : "OffsetObject";
}
System.Reflection.PropertyInfo propInfo = current.GetType().GetProperty(keyValue);
if (propInfo != null)
{
if (parser.TryConsume(out Scalar value))
{
if (propInfo.PropertyType.IsValueType || propInfo.PropertyType == typeof(string))
{
propInfo.SetValue(current, Convert.ChangeType(value.Value, propInfo.PropertyType));
}
}
else if (parser.TryConsume<SequenceStart>(out _))
{
if (typeof(IList).IsAssignableFrom(propInfo.PropertyType))
{
if (propInfo.GetValue(current) == null)
{
object propInstance = Activator.CreateInstance(propInfo.PropertyType);
propInfo.SetValue(current, propInstance);
}
var list = propInfo.GetValue(current) as IList;
var childInstance = Activator.CreateInstance(propInfo.PropertyType.GetGenericArguments().First());
list?.Add(childInstance);
while (parser.Current is MappingStart)
{
ParseNextField(parser, childInstance);
}
}
else
{
object propInstance = Activator.CreateInstance(propInfo.PropertyType);
propInfo.SetValue(current, propInstance);
while (parser.Current is MappingStart)
{
ParseNextField(parser, propInstance);
}
}
parser.Consume<SequenceEnd>();
}
}
parser.Consume<MappingEnd>();
}
/// <summary>
/// Writes the specified object's state to a YAML emitter.
/// </summary>
public void WriteYaml(IEmitter emitter, object value, Type type)
{
throw new NotImplementedException();
}
}
序列化类:
public class Message
{
public string Name { get; set; }
public string Style { get; set; }
public int PrintDelay { get; set; }
public int PrintCount { get; set; }
public Orientation Orientation { get; set; }
public PrinterDetails Printer { get; set; }
public List<Line> Line { get; set; }
}
public class Orientation
{
public int Rotation { get; set; }
public bool HFlip { get; set; }
public bool VFlip { get; set; }
}
public class PrinterDetails
{
public string Type { get; set; }
public Pitch Pitch { get; set; }
}
public class Pitch
{
public int Horizontal { get; set; }
public int VerticalAdj { get; set; }
}
public class Line
{
public List<Field> Field { get; set; }
}
public class Field
{
public string Name { get; set; }
public string Type { get; set; }
public bool Visibility { get; set; }
public int Rotation { get; set; }
public bool Negative { get; set; }
public string Locale { get; set; }
public int Boldness { get; set; }
public Position Pos { get; set; }
public Font Font { get; set; }
public Parameters Parameters { get; set; }
}
public class Parameters
{
public string Format { get; set; }
public string Text { get; set; }
public string Start { get; set; }
public string Stop { get; set; }
public int Step { get; set; }
public int Repeat { get; set; }
public int CurrentRepeat { get; set; }
public string OffsetString { get; set; }
public Offset OffsetObject { get; set; }
}
public class Offset
{
public string Time { get; set; }
}
public class Position
{
public int X { get; set; }
public int Y { get; set; }
}
public class Font
{
public string Name { get; set; }
public int Size { get; set; }
public string Units { get; set; }
public int Rotation { get; set; }
}