0

デシリアライズが機能していません。次の実行時エラーが発生します。

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() 
    {

    }
}
4

5 に答える 5

2

編集:

コンソール アプリケーションのアセンブリ名は異なるため、名前空間と型の名前が同じであっても、BinaryFormatter はアセンブリの名前を記録します。共通のクラス ライブラリ アセンブリで Measurement クラスを定義し、両方のコンソール アプリから参照します。

元の答え:

ほとんどの場合、オブジェクトをシリアル化した側は、逆シリアル化した側とは異なるバージョンのアセンブリでコンパイルされました。Measurement を含むアセンブリの AssemblyInfo.cs ファイルをチェックインして、AssemblyVersion が完全に指定されていることを確認します。

[assembly: AssemblyVersion("1.0.0.0")]

いいえ

[assembly: AssemblyVersion("1.0.*")]

それでもうまくいかない場合は、アセンブリ ファイルが両方の場所で同一であることを確認してください。

于 2011-07-11T19:43:46.750 に答える
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;
    }
}

まあ、私が public フィールドを持っていないことを除いて;p 属性が必要ない場合は、いくつかの方法で回避することもできます.

利点:

  • より速く、より小さく
  • どのプラットフォームにも関連付けられていません (C++/java/etc の protobuf クライアントに非常に簡単にロードできます)
  • 特定のタイプまたはフィールド名に関連付けられていない
  • イベントサブスクリプションなどを介して誤って余分なオブジェクトをシリアル化するリスクはありません
  • 最も一般的なシリアル化の概念を完全にサポート
于 2011-07-11T20:19:45.397 に答える
0

あなたを助けるかもしれないもう一つの解決策。BinaryFormatter の AssemblyFormat プロパティをシリアル化と逆シリアル化の両方の方法で Simple 値に設定します。

bf.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;

これは役に立ちますか?

于 2011-07-11T20:20:26.280 に答える
0

2 つのアプリケーション (1 つはシリアル化、もう 1 つは逆シリアル化) があり、それらがシリアル化された型 (測定) の DLL を共有しているが、共有 DLL が異なるビルドである場合、このエラーが発生します。

于 2011-07-11T19:45:13.427 に答える
0

推測しようとしているだけです:Measurementそのファイルのシリアル化の瞬間とは異なる名前空間にあるクラスでバイナリを逆シリアル化しようとしています。

以前にデータをシリアル化したコードを確認し、その Measurement名前空間を確認してください。

よろしく。

于 2011-07-11T19:45:20.140 に答える