簡體   English   中英

一維多維陣列-使它與protobuf一起使用

[英]Multi-Dim Array to 1D - getting it to work with protobuf

Protobuf不支持多維度數組,因此我決定使用實現從2D數組中制作1D數組。 當我調用MultiLoop函數時,在ToProtoArray方法中我Cannot cast from source type to destination type 有想法該怎么解決這個嗎?

public static ProtoArray<T> ToProtoArray<T>(this System.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));
    // ^^^^^^^^^^ cannot cast from source type to destination type
    return new ProtoArray<T> { Dimensions = dims, Data = data };
}

public static System.Array ToArray<T>(this ProtoArray<T> protoArray)
{
    // Initialize array dynamically.
    var result = System.Array.CreateInstance(typeof(T), protoArray.Dimensions);
    // Copy the underlying data.
    var k = 0;
    result.MultiLoop(indices => result.SetValue(protoArray.Data[k++], indices));

    return result;
}

public static void MultiLoop(this System.Array array, System.Action<int[]> action)
{
    array.RecursiveLoop(0, new int[array.Rank], action);
}

private static void RecursiveLoop(this System.Array array, int level, int[] indices, System.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);
        }
    }
}

[ProtoContract]
public class ProtoArray<T>
{
    [ProtoMember(1)]
    public int[] Dimensions { get; set; }
    [ProtoMember(2)]
    public T[] Data { get; set; }
}

這是我使用它來序列化2D數組的方法:

[ProtoContract]
public class Tile
{
    [ProtoMember(1)]
    public int x;
    [ProtoMember(2)]
    public int y;
    // ...
}
Tile[,] map; // meanwhile I assign the data to the array
map1d = Extensions.ToProtoArray<Tile[,]>(map);
using (var file = File.Create(path))
{
    Serializer.Serialize(file, map1d);
}

我認為這是您需要的:

public class ProtoArray<T>
{
    public ProtoArray(T[] array)
    {
        this.Data=array;
        this.Dimensions=new int[array.Length];
    }
    public ProtoArray(T[,] array)
    {
        int n = array.GetLength(0);
        int m = array.GetLength(1);
        this.Data=new T[n*m];
        for(int i = 0; i<n; i++)
        {
            for(int j = 0; j<m; j++)
            {
                // Row Major
                Data[i*m+j]=array[i, j];
                // For Column Major use Data[i+j*n]=array[i, j];
            }
        }
        this.Dimensions=new[] { n, m };
    }
    public int[] Dimensions { get; set; }
    public T[] Data { get; set; }
    public T[] ToArray()
    {
        if(Dimensions.Length==1)
        {
            return Data.Clone() as T[];
        }
        else
        {
            throw new NotSupportedException();
        }
    }
    public T[,] ToArray2()
    {
        if(Dimensions.Length==2)
        {
            int n = Dimensions[0], m = Dimensions[1];
            T[,] array = new T[n, m];
            for(int i = 0; i<n; i++)
            {
                for(int j = 0; j<m; j++)
                {
                    array[i, j]=Data[i*m+j];
                }
            }
            return array;
        }
        else
        {
            throw new NotSupportedException();
        }
    }
}

public class Tile
{
    public int x;
    public int y;
    // ...
}
class Program
{
    static void Main(string[] args)
    {
        Tile[,] map = new Tile[16, 4];

        ProtoArray<Tile> array = new ProtoArray<Tile>(map);
        //serialize array
        //
        // de-serialize array
        Tile[,] serialized_map = array.ToArray2();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM