Je suis un débutant avec YAML et j'étudie comment analyser YAML en C#. Ici, j'essaie d'analyser les modules d'objets C# où j'ai des données de types d'objets complexes tels que la classe DataTable ou la classe Type en C#. Je sais comment convertir des types de base en utilisant la bibliothèque YAMLDotNet mais je ne sais vraiment pas comment faire la même chose avec de tels types. Veuillez m'aider.
Réponse
Trop de publicités?A DataTable
est un objet complexe avec une multitude de propriétés. Le plus simple serait d'extraire les données qui vous intéressent dans une structure de données plus simple et de la sérialiser. Cependant, vous pouvez créer un IYamlTypeConverter
si tu le veux vraiment. Voici un exemple qui sérialise les noms et le type des colonnes de la table, ainsi que les valeurs des lignes :
public class DataTableTypeConverter : IYamlTypeConverter
{
public bool Accepts(Type type)
{
return typeof(DataTable).IsAssignableFrom(type);
}
public object ReadYaml(IParser parser, Type type)
{
var table = new DataTable();
parser.Expect<MappingStart>();
ReadColumns(parser, table);
ReadRows(parser, table);
parser.Expect<MappingEnd>();
return table;
}
private static void ReadColumns(IParser parser, DataTable table)
{
var columns = parser.Expect<Scalar>();
if (columns.Value != "columns")
{
throw new YamlException(columns.Start, columns.End,
"Expected a scalar named 'columns'");
}
parser.Expect<MappingStart>();
while (parser.Allow<MappingEnd>() == null)
{
var columnName = parser.Expect<Scalar>();
var typeName = parser.Expect<Scalar>();
table.Columns.Add(columnName.Value, Type.GetType(typeName.Value));
}
}
private static void ReadRows(IParser parser, DataTable table)
{
var columns = parser.Expect<Scalar>();
if (columns.Value != "rows")
{
throw new YamlException(columns.Start, columns.End,
"Expected a scalar named 'rows'");
}
parser.Expect<SequenceStart>();
while (parser.Allow<SequenceEnd>() == null)
{
var row = table.NewRow();
var columnIndex = 0;
parser.Expect<SequenceStart>();
while (parser.Allow<SequenceEnd>() == null)
{
var value = parser.Expect<Scalar>();
var columnType = table.Columns[columnIndex].DataType;
row[columnIndex] = TypeConverter.ChangeType(value.Value, columnType);
++columnIndex;
}
table.Rows.Add(row);
}
}
public void WriteYaml(IEmitter emitter, object value, Type type)
{
var table = (DataTable)value;
emitter.Emit(new MappingStart());
EmitColumns(emitter, table);
EmitRows(emitter, table);
emitter.Emit(new MappingEnd());
}
private static void EmitColumns(IEmitter emitter, DataTable table)
{
emitter.Emit(new Scalar("columns"));
emitter.Emit(new MappingStart(null, null, true, MappingStyle.Block));
foreach (DataColumn column in table.Columns)
{
emitter.Emit(new Scalar(column.ColumnName));
emitter.Emit(new Scalar(column.DataType.AssemblyQualifiedName));
}
emitter.Emit(new MappingEnd());
}
private static void EmitRows(IEmitter emitter, DataTable table)
{
emitter.Emit(new Scalar("rows"));
emitter.Emit(new SequenceStart(null, null, true, SequenceStyle.Block));
foreach (DataRow row in table.Rows)
{
emitter.Emit(new SequenceStart(null, null, true, SequenceStyle.Flow));
foreach (var item in row.ItemArray)
{
var value = TypeConverter.ChangeType<string>(item);
emitter.Emit(new Scalar(value));
}
emitter.Emit(new SequenceEnd());
}
emitter.Emit(new SequenceEnd());
}
}
Il est utilisé comme suit :
var table = new DataTable();
table.Columns.Add("id", typeof(int));
table.Columns.Add("name", typeof(string));
table.Columns.Add("description", typeof(string));
table.Rows.Add(1, "first", "The first row");
table.Rows.Add(2, "second", "The second row");
// Serialize
var serializer = new SerializerBuilder()
.WithTypeConverter(new DataTableTypeConverter())
.Build();
var yaml = serializer.Serialize(table);
// Deserialize
var deserializer = new DeserializerBuilder()
.WithTypeConverter(new DataTableTypeConverter())
.Build();
var parsedTable = deserializer.Deserialize<DataTable>(yaml);
Le YAML sérialisé dans cet exemple est :
columns:
id: System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
name: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
description: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
rows:
- [1, first, The first row]
- [2, second, The second row]