2016-11-25 10 views
1

私はYAMLを初心者にして、YAMLをC#に解析する方法を研究しています。ここでは、C#でDataTableクラスやTypeクラスなどの複雑なオブジェクト型のデータを持つC#Objectモジュールを解析しようとしています。 私はYAMLDotNetライブラリを使って基本型を変換する方法を知っていますが、実際にはそのような型をどうやって行うのか分かりません。 助けてください。C#の複雑な型をYAMLに変換する

答えて

0

DataTableは、プロパティが失われた複雑なオブジェクトです。最も簡単な方法は、あなたに関連するデータをより単純なデータ構造に抽出し、代わりにそれをシリアル化することです。ただし、本当にしたい場合は、カスタムIYamlTypeConverterを作成することができます。ここでは、テーブルの列名とタイプだけでなく、行の値をシリアル化します例です。

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()); 
    } 
} 

次のようにそれが使用されている:

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); 

この例では、シリアライズYAMLがあります:

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] 
+0

ありがとう:)それは(y) – Anonymous

関連する問題