【问题标题】:I cannot deserialize data previously serialized successfully我无法反序列化以前成功序列化的数据
【发布时间】:2013-04-22 04:03:35
【问题描述】:

我在 Google 中随机输入“最快的序列化 c#”,结果得到了 protobuf.net。我试过了,我认为我可以正确序列化但由于我无法反序列化,现在无法判断是否存在?!

当我试图反序列化时,我得到:

A first chance exception of type 'ProtoBuf.ProtoException' occurred in protobuf-net.dll

酷。

要序列化的数据:

[ProtoContract]
public struct Cow
{
    [ProtoMember(1)]
    public float Weight{ get; private set; }
    [ProtoMember(2)]
    public bool[] HadCowlings{ get; private set; }

    public Cow(float weight, bool[] babies)
        : this()
    {
        this.Weight = weight;
        this.HadCowlings= (bool[])babies.Clone();
    }
...
}

[ProtoContract]
public class Pasture
{
    [ProtoMember(1)]
    public Point Position { get; private set; }
    [ProtoMember(2)]
    public Cow[] Cows { get; private set; }

    public static int HerdSize { get; private set; }

    public static float BoundWidth { get; private set;}
    public static float BoundHeight { get; private set; }

    public Pasture(Cow[] Cows, Point farmPosition)
    {
        this.Cows = (Cow[])Cows.Clone();
        Position = farmPosition;
    }
...
}

[ProtoContract]
public class Farm
{
    [ProtoMember(1)]
    public Point FarmIDCoordinates{ get; private set; }
    [ProtoMember(2)]
    public List<Pasture> Pastures{ get; private set; }

    public static float BoundWidth { get; private set; }
    public static float BoundHeight { get; private set; }

    public static int FarmSize { get; private set; }

    public Farm(int x, int y, FarmType fType)
    {
        if (fType == RegionType.STANDARD)
            Pastures = new List<Pasture>(//make a farm!);
        else
            Pastures = new List<Pasture>(//What he said);

        FarmIDCoordinates = new Point(x, y);
    }
...
}

方法:

设置:

 using (ObjectSerializer serializer = new ObjectSerializer())
{
     serializer.ProtoSerialize<Farm>(farm.ToString() + ".bin", aFarm)
}

获取:

using (ObjectSerializer serializer = new ObjectSerializer())
{
   try
   {
      farmsIOwn.Add(serializer.ProtoDeserialize<Farm>(
                  farmLat.X.ToString() + "_" + farmLong.Y.ToString() + ".bin"));
   }
   catch
   {
      // make me a dummy farm, crashing is for dummies
   }
}

ObjectSerializer:

public void ProtoSerialize<T>(string fileName, T objectGraph)
{

   using (var stream = File.Open(fileName, FileMode.Create))
   {
       Serializer.Serialize<T>(stream, objectGraph);
   }
}

public T ProtoDeserialize<T>(string fileName)
{
    T objectGraph;

    using (var stream = File.Open(fileName, FileMode.Open))
    {
       objectGraph = Serializer.Deserialize<T>(stream);
    }

    return objectGraph;
}

【问题讨论】:

  • 您几乎应该忽略第一次机会异常 - 它们真的不存在。 actual 异常会告诉您它正在寻找构造函数等。

标签: c# protobuf-net


【解决方案1】:

protobuf-net 可以通过多种不同的方式进行配置。默认情况下,它通过无参数构造函数创建对象,因为该选项适用于所有框架。这种用法有点像XmlSerializer。因为您的类型没有构造函数,所以这种用法不起作用。最简单的选择是添加一个无参数构造函数。要在完整框架上使用,它不需要是 public - 所以 private / protected 等构造函数很好 - 但请注意,这 (private / protected) 不适用于 Silverlight 等.

下一个选项是完全跳过构造函数——很像DataContractSerializer。这可以通过属性或类型模型的运行时配置来完成。为了说明第一个:

[ProtoContract(SkipConstructor = true)]
public class Foo {...}

再说一遍 - 这在大多数框架上都很好用,但也有一些不起作用(根本不存在实现它的框架实用程序方法)。

最后,您可以提供自己的工厂方法;每个类型的全局。这个工厂方法是一个 static 方法,它返回一个 vanilla 实例(可选地接受序列化上下文、请求类型等)。除了提供对构造的完全控制之外,如果您想提供对象池等,这也很有用。此选项适用于所有框架,但需要您编写额外的代码和配置。

【讨论】:

  • 对如何添加“通过类型模型的运行时配置”感兴趣
【解决方案2】:

protobuf-net 的要求之一是提供默认构造函数。 因为 Farm 和 Pasture 对象的构造函数都包含参数。不再有默认构造函数。您必须提供一份。

添加一个以获取您的数据。

Farm() {}

Pastures() {}

【讨论】:

  • 其实这不是必须的。
  • @MarGravell 我猜这个练习的重点是这样的要求对于像我这样的人来说并不明显。欢迎该工具的作者提供更深入的文档。我知道你很忙,所以我希望我可以为我班的人填补任何空白。
猜你喜欢
  • 1970-01-01
  • 2013-04-26
  • 2011-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-26
  • 2018-03-06
相关资源
最近更新 更多