子类化数据表在序列化/反序列化期间将数据类型信息从双精度更改为字符串
本文关键字:信息 数据类型 双精度 字符串 数据表 序列化 反序列化 子类 | 更新日期: 2023-09-27 18:37:23
作为这个问题的背景,我想将一个"代码制作"DataTable
绑定到一个aspx:GridView
。为了保留此表,我实现了ISerializable
接口。表显示正确,但在对行进行排序的回发中,由于行中的元素,会引发InvalidCastExcpetion
。项目数组从类型 double
更改为类型 string
。
注意:两个构造函数,一个用于构造 DataTable 初始值,另一个用于在反序列化过程中构造表:
[global::System.Serializable()]
[global::System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedTableSchema")]
public partial class HeatMapVisualisationDataTable : DataTable, System.Runtime.Serialization.ISerializable
{
#region members
public double _valueMin { get; private set; }
public double _valueMax { get; private set; }
#endregion membders
public HeatMapVisualisationDataTable(XemlExperimentHeatMapDataTable data)
: base("result", "http://gmd.mpimp-golm.mpg.de/HeatMap")
{
this.Columns.Add(new DataColumn("metabolite", typeof(Guid)));
this.Columns.Add(new DataColumn("name", typeof(string)));
DataColumn[] PrimaryKeyColumns = new DataColumn[1];
PrimaryKeyColumns[0] = this.Columns["metabolite"];
this.PrimaryKey = PrimaryKeyColumns;
SortedDictionary<int, DataColumn> headers = new SortedDictionary<int, DataColumn>();
foreach (var item in data.AsParallel().AsEnumerable().Select(x => x.ObservationPointId).Distinct().OrderBy(x => x))
{
DataColumn dc = this.Columns.Add(item.ToString(), typeof(Double));
headers.Add(item, dc);
}
foreach (var item in data)
{
DataRow tmpRow = base.Rows.Find(item.MetaboliteId);
if (tmpRow == null)
{
tmpRow = base.Rows.Add(new object[] { item.MetaboliteId });
tmpRow["name"] = item.MetaboliteName;
}
tmpRow[headers[item.ObservationPointId]] = item.value;
}
this.AcceptChanges();
_valueMax = data.AsParallel().AsUnordered().Max(x => x.value);
_valueMin = data.AsParallel().AsUnordered().Min(x => x.value);
}
public HeatMapVisualisationDataTable(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext ctxt) :
base(info, ctxt)
{
_valueMin = (double)info.GetValue("valueMin", typeof(double));
_valueMax = (double)info.GetValue("valueMax", typeof(double));
}
public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext ctxt)
{
base.GetObjectData(info, ctxt);
info.AddValue("valueMin", _valueMin);
info.AddValue("valueMax", _valueMax);
}
}
正如我可以通过读取构造函数HeatMapVisualisationDataTable(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext ctxt)
中SerializationInfo
中的模式所观察到的那样,该表是正确的序列化的,并且就丝网化的 xml 模式而言,它来自"存储"。但是,查看此构造函数中的构造基类,用于序列化的所有类型为 double
的列现在都是 string
类型。我做错了什么?
更新 1:我还可以通过将数字数据类型从 double
更改为 float
或 decimal
来重现此问题。类型 Guid
的主键列将反序列化为正确的类型。
更新2:在我看来,所描述的行为是一些DataTable.ReadXml()
问题的后续,其中列的数据类型被字符串替换。
谢谢一月
作为一种解决方案,通过绕过DataTable的序列化为XML,然后使用ReadXml
从XML重新创建DataTable,我使用了这篇关于 ADO.NET 对象的二进制序列化的MSDN文章。诀窍是将有关列名和列类型的信息存储在一些额外的ArrayList
中,并将其放入序列化中。在这里查看我当前的ISerializable
接口实现:
public HeatMapVisualisationDataTable(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext ctxt)
base()
{
_valueMin = info.GetSingle("valueMin");
_valueMax = info.GetSingle("valueMax");
System.Collections.ArrayList colNames = (System.Collections.ArrayList)info.GetValue("colNames", typeof(System.Collections.ArrayList));
System.Collections.ArrayList colTypes = (System.Collections.ArrayList)info.GetValue("colTypes", typeof(System.Collections.ArrayList));
System.Collections.ArrayList dataRows = (System.Collections.ArrayList)info.GetValue("dataRows", typeof(System.Collections.ArrayList));
// Add columns
for (int i = 0; i < colNames.Count; i++)
{
DataColumn col = new DataColumn(colNames[i].ToString(), Type.GetType(colTypes[i].ToString()));
this.Columns.Add(col);
}
// Add rows
for (int i = 0; i < dataRows.Count; i++)
{
DataRow row = this.Rows.Add((object[])dataRows[i]);
}
this.AcceptChanges();
}
public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext ctxt)
{
System.Collections.ArrayList colNames = new System.Collections.ArrayList();
System.Collections.ArrayList colTypes = new System.Collections.ArrayList();
System.Collections.ArrayList dataRows = new System.Collections.ArrayList();
foreach (DataColumn col in this.Columns)
{
colNames.Add(col.ColumnName);
colTypes.Add(col.DataType.FullName);
}
foreach (DataRow row in this.Rows)
{
dataRows.Add(row.ItemArray);
}
info.AddValue("colNames", colNames);
info.AddValue("colTypes", colTypes);
info.AddValue("dataRows", dataRows);
info.AddValue("valueMin", _valueMin);
info.AddValue("valueMax", _valueMax);
}
请注意,我不再调用 DataTable 的 GetObjectData(...)
和构造函数进行反序列化。但是,这不是我原始帖子的答案。这只是一种解决方法...所以"ReadXml()
为什么要改变数据类型?"这个问题仍然悬而未决!