【问题标题】:What mistake am I making when serializing?序列化时我犯了什么错误?
【发布时间】:2013-04-20 14:13:27
【问题描述】:

这会导致运行时出现序列化异常。这只是一个演示项目,用于测试执行此操作的最佳方法。我包括了主要方法和我试图序列化的类。

忽略:我真的不能添加更多细节,我已经描述了问题,附上了代码,这个“请添加更多细节”的事情是有史以来最愚蠢的事情。让我已经发布了。

Data toSend = new Data();
toSend.Output();

///SERIALIZE

BinaryFormatter formatter = new BinaryFormatter();
Stream streamOut = File.OpenWrite("file");
formatter.Serialize(streamOut, toSend);
streamOut.Close();


Console.WriteLine("----------------------------");
///DESERIALIZE

Stream streamIn = File.OpenRead("file");
Object received = formatter.Deserialize(streamIn);
Data toReceive = (Data)received;
toReceive.Output();

class Data : ISerializable
{
    int integerData;
    string stringData;
    bool booleanData;
    int shouldnotbeserialized;

    public Data()
    {
        integerData = 1;
        stringData = "Hello";
        booleanData = true;
        shouldnotbeserialized = 55;
    }

    //To deserialize
    public Data(SerializationInfo info, StreamingContext context)
    {
        integerData = info.GetInt32("theint");
        stringData = info.GetString("thestring");
        booleanData = info.GetBoolean("thebool");
    }

    public void Output()
    {
        Console.WriteLine(integerData);
        Console.WriteLine(stringData);
        Console.WriteLine(booleanData);
        Console.WriteLine(shouldnotbeserialized);
    }

    //Implemented method to serialize
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("thestring", stringData);
        info.AddValue("theint", integerData);
        info.AddValue("thebool", booleanData);
    }
}

异常信息:

在程序集“SerializationDemo”中键入“SerializationDemo.Data”, Version=1.0.0.0,Culture=neutral,PublicKeyToken=null' 未标记 作为可序列化的。

【问题讨论】:

  • @walther 在程序集“SerializationDemo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”中键入“SerializationDemo.Data”未标记为可序列化。
  • 等等...这是否意味着,我也需要 [] 属性?从接口派生还不够吗?
  • [Serializable] 是你所需要的
  • 好的,这就是问题所在……但我仍然不明白当属性将一个类标记为可序列化时会做什么。
  • 我确定有一个重复的问题,缺少属性是问题所在。

标签: c# serialization


【解决方案1】:

在异常信息中给你答案:

在程序集“SerializationDemo”中键入“SerializationDemo.Data”, Version=1.0.0.0,Culture=neutral,PublicKeyToken=null' 未标记 作为可序列化的。

您需要使用Serializable 属性标记您的班级。

[Serializable()]
class Data : ISerializable

从上下文看来,您将通过网络传输对象(由局部变量名称 toSendtoReceive 推断)。您需要注意,例如,如果您使用客户端-服务器模型,默认情况下,从服务器软件序列化和发送的对象将无法从客户端软件反序列化。

这是因为二进制序列化的基本特征是它保留了类型系统保真度。类型系统保真度表示类型信息在序列化过程中不会丢失。这意味着当您序列化一个对象时,不仅是写入数据流的“对象的状态”,还有类的名称和包含的程序集。即使您在要反序列化数据的程序集中定义了类Data,反序列化方法也会失败(抛出异常),因为反序列化器将寻找类型Program1.Namespace.Data 而不是Program2.Namespace.Data。为了解决这个问题,您可以在相互程序集(类库)中定义您的数据消息,或者通过定义SerializationBinder 这将允许您基本上欺骗反序列化方法认为您仍在同一个程序集中。

【讨论】:

  • 它比我想象的要复杂,这只是一个虚拟测试程序,但是是的,我的目的是通过 tcp 连接发送它。那么在 DLL 中定义类并在服务器和客户端项目中链接它是一个好策略吗?上下文是一个多人国际象棋应用程序,我想传输棋盘实例。
  • @Innkeeper 我认为在他们自己的程序集中定义你的消息是一个好主意,因为它使序列化过程更容易,这也意味着你不必复制和粘贴类,可能还有枚举每次添加新消息时跨程序集的消息标识符的数量。唯一的缺点是,您的应用程序将依赖于您的 DLL,并且不再是独立的可执行文件。
猜你喜欢
  • 2023-01-13
  • 2017-10-12
  • 1970-01-01
  • 2016-12-09
  • 2023-03-03
  • 2021-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多