C# 无法反序列化数据表
本文关键字:数据表 反序列化 | 更新日期: 2023-09-27 18:35:07
我有一个客户端/服务器项目,我正在尝试通过套接字将数据表(从TableAdapter中提取)从服务器发送到客户端。我的服务器命名空间是 srvCentral,我的客户端是 appClient。当我尝试在客户端中反序列化 DataTable 时,它会抛给我一个序列化异常,说找不到程序集"srvCentral,版本=1.0.0.0,区域性=中性,公钥令牌=空"我已经用谷歌搜索并尝试了一些事情,例如控制AssemblyResolve,这使得svchost挂起并迫使我关闭,并使用这样的活页夹:
sealed class AllowAllAssemblyVersionsDeserializationBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
Type typeToDeserialize = null;
String currentAssembly = Assembly.GetExecutingAssembly().FullName;
// In this case we are always using the current assembly
assemblyName = currentAssembly;
// Get the type using the typeName and assemblyName
typeToDeserialize = Type.GetType(String.Format("{0}, {1}",
typeName, assemblyName));
return typeToDeserialize;
}
}
例外仍然在那里...数据表不是应该在任何地方反序列化吗?我做错了什么?
我的序列化代码是:
public byte[] Serializar(Object item)
{
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
formatter.Serialize(ms, item);
return ms.ToArray();
}
public Object Deserializar(byte[] buffer)
{
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream ms = new MemoryStream(buffer);
formatter.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
formatter.Binder = new AllowAllAssemblyVersionsDeserializationBinder();
Object a = formatter.Deserialize(ms);
return a;
}
sealed class AllowAllAssemblyVersionsDeserializationBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
Type typeToDeserialize = null;
String currentAssembly = Assembly.GetExecutingAssembly().FullName;
// In this case we are always using the current assembly
assemblyName = currentAssembly;
// Get the type using the typeName and assemblyName
typeToDeserialize = Type.GetType(String.Format("{0}, {1}",
typeName, assemblyName));
return typeToDeserialize;
}
}
经过一番挖掘,我已经解决了这个问题;
这不是解决它的更好方法,但却是避免问题的简单方法。对于小事就足够了。如果要从表中检索仅用于显示内容的数据,请使用此选项。
namespace YourLibrary
{
[Serializable]
public class Tabela: ISerializable
{
protected ArrayList colNames;
protected ArrayList colTypes;
protected ArrayList dataRows;
public Tabela()
{
}
public Tabela (DataTable dt)
{
colNames = new ArrayList();
colTypes = new ArrayList();
dataRows = new ArrayList();
// Insert column information (names and types)
foreach(DataColumn col in dt.Columns)
{
colNames.Add(col.ColumnName);
colTypes.Add(col.DataType.FullName);
}
// Insert rows information
foreach(DataRow row in dt.Rows)
dataRows.Add(row.ItemArray);
}
public Tabela(SerializationInfo info, StreamingContext context)
{
colNames = (ArrayList)info.GetValue("colNames",typeof(ArrayList));
colTypes = (ArrayList)info.GetValue("colTypes",typeof(ArrayList));
dataRows = (ArrayList)info.GetValue("dataRows",typeof(ArrayList));
}
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("colNames", colNames);
info.AddValue("colTypes", colTypes);
info.AddValue("dataRows", dataRows);
}
public DataTable GenerateDataTable()
{
DataTable dt = new DataTable();
// Add columns
for(int i=0; i<colNames.Count; i++)
{
DataColumn col = new DataColumn(colNames[i].ToString(),
Type.GetType(colTypes[i].ToString() ));
dt.Columns.Add(col);
}
// Add rows
for(int i=0; i<dataRows.Count; i++)
{
DataRow row = dt.NewRow();
row.ItemArray = (object[]) dataRows[i];
dt.Rows.Add(row);
}
dt.AcceptChanges();
return dt;
}
}
}
我做错了什么?
叹息; 1:使用DataTable
,2:使用BinaryFormatter
让我们先看后者; BinaryFormatter
是以类型为中心的序列化程序。实际上,如果您只是使用 DataTable
而不是类型化的 DataTable
子类,您可能会侥幸逃脱,但BinaryFormtter
最终希望在两端使用完全相同的类型。而你没有那个。即使你这样做了,每次你对管道的一端进行版本控制时,事情可能会变得有点......狡猾(除非你为此投入额外的精力)。
作为临时修复,对于此步骤,只需使用 DataTable
而不是类型化的 DataTable
子类,它可能会起作用。
然而,DataTable
也是一件非常尴尬的事情 - 相当笨拙,目的如此笼统。如果您需要它提供的内容(特别是动态列),那么....也许在推动下,但在大多数情况下,使用基本的POCO/DTO模型会更可取。这也更容易在客户端/服务器边界上表达,包括大多数 IPC 工具。例如,以下POCO/DTO类(或它们的列表)非常友好:
public class Order {
public int OrderID {get;set;}
public string Reference {get;set;}
...
}
就个人而言,我强烈建议您考虑切换到更简单的、基于类的模型,使用对特定类型不挑剔的序列化程序; XmlSerializer
或JavascriptSerializer
工作得很好。如果您需要小/高效的数据,那么protobuf-net也值得一看。所有这些在套接字上也都很好用。