反序列化无效。它给了我以下运行时错误:
Unhandled Exception: System.InvalidCastException: Unable to cast object of 'Measurement' to type 'Measurement'.
我真的看不出它有什么问题。
//start alternate serialization
public static class AltSerialization
{
public static byte[] AltSerialize(Measurement m)
{
using (var ms = new MemoryStream())
{
var bf = new BinaryFormatter();
bf.Serialize(ms, m);
return ms.GetBuffer();
}
}
public static Measurement AltDeSerialize(byte[] seriM)
{
using (var stream = new MemoryStream( seriM ))
{
BinaryFormatter bf = new BinaryFormatter();
return (Measurement)bf.Deserialize(stream);
}
}
}
//end alternte serialization
[Serializable] //This attribute sets class to be serialized
public class Measurement : ISerializable
{
[NonSerialized] public int id;
public int time; //timestamp
public double value;
public Measurement()
{
id = 1;
time = 12;
value = 0.01;
}
public Measurement(int _id, int _time, double _value)
{
id = _id;
time = _time;
value = _value;
}
//Deserialization constructor
public Measurement(SerializationInfo info, StreamingContext ctxt)
{
//Assign the values from info to the approporiate properties
Console.WriteLine("DeSerialization construtor called.");
time = (int)info.GetValue("MeasurementTime", typeof(int));
value = (double)info.GetValue("MeasurementValue", typeof(double));
}
//Serialization function
public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
{
// Custom name-value pair
// Values must be read with the same name they're written
info.AddValue("MeasurementTime", time);
info.AddValue("MeasurementValue", value);
}
}
//AFTER THIS, IS FOR TEST FILES app1.cs, app2.cs, and the reference refer.cs.
//app1.cs
using System;
using System.IO;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using refer;
using System.Reflection;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
[assembly: AssemblyVersion("1.0.0.0")]
public class MainClass
{
public static void Main()
{
//Create a new Measurement message
Measurement m1 = new Measurement(2, 2345, 23.456);
System.Console.WriteLine("\nm1.id = {0}", m1.id);
System.Console.WriteLine("m1.time = {0}", m1.time);
System.Console.WriteLine("m1.value = {0}", m1.value);
/*byte[] bArray = AltSerialization.AltSerialize( m1 );
Measurement m2 = new Measurement();
m2 = AltSerialization.AltDeSerialize(bArray);
System.Console.WriteLine("\nm2.id = {0}", m2.id);
System.Console.WriteLine("m2.time = {0}", m2.time);
System.Console.WriteLine("m2.value = {0}", m2.value);*/
ConnectionFactory factory = new ConnectionFactory();
factory.HostName = "localhost";
using (IConnection connection = factory.CreateConnection())
using (IModel channel = connection.CreateModel())
{
channel.QueueDeclare("hello", true, false, false, null);
byte[] body = refer.AltSerialization.AltSerialize( m1 );
channel.BasicPublish("", "hello", null, body);
Console.WriteLine(" [x] Sent ");
}
}
}
//app2.cs
using System;
using System.IO;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using refer;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System.Reflection;
[assembly: AssemblyVersion("1.0.0.0")]
public class MainClass
{
public static void Main()
{
/*/Create a new Measurement message
Measurement m1 = new Measurement(2, 2345, 23.456);
System.Console.WriteLine("\nm1.id = {0}", m1.id);
System.Console.WriteLine("m1.time = {0}", m1.time);
System.Console.WriteLine("m1.value = {0}", m1.value);
byte[] bArray = AltSerialization.AltSerialize( m1 );*/
Measurement m2 = new Measurement();
ConnectionFactory factory = new ConnectionFactory();
factory.HostName = "localhost";
using (IConnection connection = factory.CreateConnection())
using (IModel channel = connection.CreateModel()) {
channel.QueueDeclare("hello", false, false, false, null);
QueueingBasicConsumer consumer = new QueueingBasicConsumer(channel);
channel.BasicConsume("hello", true, consumer);
System.Console.WriteLine(" [*] Waiting for messages." +
"To exit press CTRL+C");
BasicDeliverEventArgs ea =
(BasicDeliverEventArgs)consumer.Queue.Dequeue();
m2 = refer.AltSerialization.AltDeSerialize(ea.Body);
System.Console.WriteLine(" \n[x] Received ");
System.Console.WriteLine("\nm2.id = {0}", m2.id);
System.Console.WriteLine("m2.time = {0}", m2.time);
System.Console.WriteLine("m2.value = {0}", m2.value);
}
}
}
//refer.cs
using System;
using System.IO;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Reflection;
[assembly: AssemblyVersion("1.0.0.0")]
namespace refer
{
//start alternate serialization
public static class AltSerialization
{
public static byte[] AltSerialize(Measurement m)
{
using (var ms = new MemoryStream())
{
var bf = new BinaryFormatter();
bf.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
bf.Serialize(ms, m);
return ms.GetBuffer();
}
}
public static Measurement AltDeSerialize(byte[] seriM)
{
using (var stream = new MemoryStream( seriM ))
{
BinaryFormatter bf = new BinaryFormatter();
bf.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
return (Measurement)bf.Deserialize(stream);
}
}
}
//end alternte serialization
[Serializable] //This attribute sets class to be serialized
public class Measurement : ISerializable
{
[NonSerialized] public int id;
public int time; //timestamp
public double value;
public Measurement()
{
id = 1;
time = 12;
value = 0.01;
}
public Measurement(int _id, int _time, double _value)
{
id = _id;
time = _time;
value = _value;
}
//Deserialization constructor
public Measurement(SerializationInfo info, StreamingContext ctxt)
{
//Assign the values from info to the approporiate properties
Console.WriteLine("DeSerialization construtor called.");
time = (int)info.GetValue("MeasurementTime", typeof(int));
value = (double)info.GetValue("MeasurementValue", typeof(double));
}
//Serialization function
public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
{
// Custom name-value pair
// Values must be read with the same name they're written
info.AddValue("MeasurementTime", time);
info.AddValue("MeasurementValue", value);
}
}
}
public class MainClass
{
public static void Main()
{
}
}
答案 0 :(得分:2)
编辑:
控制台应用程序的程序集名称不同,因此即使命名空间和类型名称相同,BinaryFormatter仍会记录程序集的名称。在公共类库程序集中定义Measurement类,并从两个控制台应用程序引用它。
原始答案:
最有可能的是,序列化对象的那一方是使用不同版本的程序集编译的,而不是反序列化它的那一方。在AssemblyInfo.cs文件中检查包含Measurement的程序集,以确保完全指定AssemblyVersion。
[assembly: AssemblyVersion("1.0.0.0")]
不
[assembly: AssemblyVersion("1.0.*")]
如果这不起作用,请确保两个地方的程序集文件相同。
答案 1 :(得分:0)
如果您有两个应用程序,一个序列化和一个反序列化,并且它们与序列化类型(Measurment)共享DLL,但共享DLL是不同的构建版本,则会出现此错误。
答案 2 :(得分:0)
只是想猜测:你正在尝试使用Measurement
类反序列化二进制文件,该类现在位于不同的命名空间中,然后在该文件的序列化时刻。
检查先前已对您的数据进行序列化的代码,并检查 Measurement
名称与您的关系。
问候。
答案 3 :(得分:0)
由于(评论)你表示有兴趣避免这种情况,所以我会这样做:
using System.IO;
using ProtoBuf;
public static class AltSerialization
{
public static byte[] AltSerialize(Measurement m)
{
using (var ms = new MemoryStream())
{
Serializer.Serialize(ms, m);
return ms.ToArray();
}
}
public static Measurement AltDeSerialize(byte[] seriM)
{
using (var stream = new MemoryStream(seriM))
{
return Serializer.Deserialize<Measurement>(stream);
}
}
}
[ProtoContract]
public class Measurement
{
public int id; // not serialized
[ProtoMember(1)]
public int time; // serialized as field 1
[ProtoMember(2)]
public double value; // serialized as field 2
public Measurement()
{
id = 1;
time = 12;
value = 0.01;
}
public Measurement(int _id, int _time, double _value)
{
id = _id;
time = _time;
value = _value;
}
}
好吧,除了我没有公共字段; p如果你不想要这些属性,也可以通过多种方式避免它们,如果你真的想要我可以解释。
优点:
答案 4 :(得分:0)
还有一个解决方案可能对您有所帮助。在序列化和反序列化方法中将BinaryFormatter的AssemblyFormat属性设置为Simple值:
bf.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
这有帮助吗?