具有多维数组的Protobuf [英] Protobuf with Multidimensional Array
问题描述
我正在为c#xna开发的游戏进行保存和加载.我有一长串要尝试序列化的类数组,我遇到了其中一个问题.我已经完成了像下面这样的课程
I'm working on saving and loading for a game being developed in c# xna. I have a long list of class arrays that I'm trying to serialize and im coming across a problem with one of them. Ive done the class like the following
[ProtoContract]
public class CompleteTile
{
int _id;
[ProtoMember(1)]
public int ID
{
get { return _id; }
set { _id = value; }
}
bool _Passable;
[ProtoMember(2)]
public bool Passable
{
get { return _Passable; }
set { _Passable = value; }
}
我可以使用
using (var stream = File.OpenWrite("" + saveDestination + "level.dat"))
{ Serializer.Serialize(stream, Globals.levelArray); }
但是当我尝试反序列化时,我得到以下信息-类型不是预期的,并且不能推断出任何合同:GameName1.CompleteTile [,,]
But when I try to deserialize I get the following - Type is not expected, and no contract can be inferred: GameName1.CompleteTile[,,]
反序列化代码-
using (var stream = File.OpenRead("" + loadDestination + "level.dat"))
{ Globals.levelArray = Serializer.Deserialize<CompleteTile[, ,]>(stream); }
我怀疑这是由于它是多维数组,但我不确定,任何帮助都将受到赞赏.
I suspect this is due to it being a multidimensional array but I'm not sure, any help is appreciated.
推荐答案
如上所述,protobuf不支持多维数组.但是,您可以通过将多维数组转换为1D数组+整数维数组来规避此限制.为了减轻痛苦,我使用了一些扩展名
As already mentioned, protobuf does not support multidimensional arrays. However, you can circumvent this limitation by transforming the multidimensional array into a 1D array + a dimensional array of integers. To easy the pain, I use a few extensions
public static class Extensions
{
#region Multidimensional array handling
public static ProtoArray<T> ToProtoArray<T>(this Array array)
{
// Copy dimensions (to be used for reconstruction).
var dims = new int[array.Rank];
for (int i = 0; i < array.Rank; i++) dims[i] = array.GetLength(i);
// Copy the underlying data.
var data = new T[array.Length];
var k = 0;
array.MultiLoop(indices => data[k++] = (T) array.GetValue(indices));
return new ProtoArray<T> {Dimensions = dims, Data = data};
}
public static Array ToArray<T>(this ProtoArray<T> protoArray)
{
// Initialize array dynamically.
var result = Array.CreateInstance(typeof(T), protoArray.Dimensions);
// Copy the underlying data.
var k = 0;
result.MultiLoop(indices => result.SetValue(protoArray.Data[k++], indices));
return result;
}
#endregion
#region Array extensions
public static void MultiLoop(this Array array, Action<int[]> action)
{
array.RecursiveLoop(0, new int[array.Rank], action);
}
private static void RecursiveLoop(this Array array, int level, int[] indices, Action<int[]> action)
{
if (level == array.Rank)
{
action(indices);
}
else
{
for (indices[level] = 0; indices[level] < array.GetLength(level); indices[level]++)
{
RecursiveLoop(array, level + 1, indices, action);
}
}
}
#endregion
}
[ProtoContract]
public class ProtoArray<T>
{
[ProtoMember(1)]
public int[] Dimensions { get; set; }
[ProtoMember(2)]
public T[] Data { get; set; }
}
并将每个多维数组持久化为ProtoArray.
and persist each multidimensional arrays as a ProtoArray.
这篇关于具有多维数组的Protobuf的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!