static void ProtoWrite(DataTable table, Stream stream) { using (var writer = new ProtoWriter(stream, null, null)) { // table name if (!string.IsNullOrEmpty(table.TableName)) { ProtoWriter.WriteFieldHeader(1, WireType.String, writer); ProtoWriter.WriteString(table.TableName, writer); } // write the schema: var cols = table.Columns; Action <object>[] colWriters = new Action <object> [cols.Count]; int i = 0; foreach (DataColumn col in cols) { // for each, write the name and data type ProtoWriter.WriteFieldHeaderAnyType(2, WireType.StartGroup, writer); var token = ProtoWriter.StartSubItemWithoutWritingHeader(col, writer); ProtoWriter.WriteFieldHeader(1, WireType.String, writer); ProtoWriter.WriteString(col.ColumnName, writer); ProtoWriter.WriteFieldHeader(2, WireType.Variant, writer); MappedType type; switch (Type.GetTypeCode(col.DataType)) { case TypeCode.Decimal: type = MappedType.Decimal; break; case TypeCode.Int16: type = MappedType.Int16; break; case TypeCode.Int32: type = MappedType.Int32; break; case TypeCode.String: type = MappedType.String; break; case TypeCode.DateTime: type = MappedType.DateTime; break; default: if (col.DataType == typeof(Guid)) { type = MappedType.Guid; break; } throw new NotSupportedException(col.DataType.Name); } ProtoWriter.WriteInt32((int)type, writer); ProtoWriter.EndSubItem(token, writer); int field = i + 1; Action <object> colWriter; switch (type) { case MappedType.String: colWriter = value => { ProtoWriter.WriteFieldHeader(field, WireType.String, writer); ProtoWriter.WriteString((string)value, writer); }; break; case MappedType.Int16: colWriter = value => { ProtoWriter.WriteFieldHeader(field, WireType.Variant, writer); ProtoWriter.WriteInt16((short)value, writer); }; break; case MappedType.Decimal: colWriter = value => { ProtoWriter.WriteFieldHeader(field, WireType.StartGroup, writer); BclHelpers.WriteDecimal((decimal)value, writer); }; break; case MappedType.Int32: colWriter = value => { ProtoWriter.WriteFieldHeader(field, WireType.Variant, writer); ProtoWriter.WriteInt32((int)value, writer); }; break; case MappedType.Guid: colWriter = value => { ProtoWriter.WriteFieldHeader(field, WireType.StartGroup, writer); BclHelpers.WriteGuid((Guid)value, writer); }; break; case MappedType.DateTime: colWriter = value => { ProtoWriter.WriteFieldHeader(field, WireType.StartGroup, writer); BclHelpers.WriteDateTime((DateTime)value, writer); }; break; default: throw new NotSupportedException(col.DataType.Name); } colWriters[i++] = colWriter; } // write the rows foreach (DataRow row in table.Rows) { i = 0; ProtoWriter.WriteFieldHeaderAnyType(3, WireType.StartGroup, writer); var token = ProtoWriter.StartSubItemWithoutWritingHeader(row, writer); foreach (DataColumn col in cols) { var value = row[col]; if (value == null || value is DBNull) { } else { colWriters[i](value); } i++; } ProtoWriter.EndSubItem(token, writer); } } }