I cannot deserialize data previously serialized successfully

跟風遠走 提交于 2019-12-24 02:07:36

问题


I was randomly typing 'fastest serializing c#' into Google and got protobuf.net as a result. I tried it and I think I can serialize properly yet since I can't deserilize, there is no way to tell now is there?!

When trying to deserilaize I get :

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

Cool.

The Data To Serialize:

[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);
    }
...
}

The How:

Set:

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

Get:

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;
}

回答1:


protobuf-net can be configured in many different ways. By default, it creates objects via a parameterless constructor, because that option that works on all frameworks. In this usage, it is a bit like XmlSerializer. Because your types don't have a constructor, that usage can't work. The simplest option is to add a parameterless constructor. For use on the full framework this does not need to be public - so a private / protected etc constructor is fine - but note that this (private / protected) won't work on Silverlight etc.

The next option is to skip the constructor completely - a lot like DataContractSerializer. This can be done via attributes or via runtime configuration of the type-model. To illustrate the first:

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

Again - this works great on most frameworks, but there are a few where it doesn't work (the framework utility method to do it simply doesn't exist).

Finally, you can provide your own factory methods; either per-type of globally. This factory method is a static method that returns a vanilla instance (optionally accepting things like the serialization-context, requested-type, etc). In addition to providing complete control over construction, this is also useful if you want to provide object-pooling etc. This option works on all frameworks, but requires you to write extra code and configuration.




回答2:


One of the requirements of protobuf-net is that a default constructor be provided. Because both Farm and Pasture objects' constructors contain parameters. There is no longer a default constructor. You must provide one.

Add one to get your data back.

Farm() {}

Pastures() {}


来源:https://stackoverflow.com/questions/16139241/i-cannot-deserialize-data-previously-serialized-successfully

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!