2017-07-18 25 views
2

我正在開發一個應用程序,它使用飛躍運動設備,並使用C#實現的過程中,我的問題是,我想存儲包含在我的數據庫中的向量的列表。所以我想過一個將矢量轉化爲浮點數組的解決方案,問題是每個列表包含最大值和最小值(存儲到數據庫中需要花費大量時間)。「類型不是預期的,並且不能推斷出合同:Leap.Vector」錯誤。使用Protobuf網絡串行器

因此,我尋找其他可能的存儲方式,並結束了.net序列化的主題。我曾嘗試實現內置的.net序列化。認爲它的工作,但仍然需要大約一分鐘序列化列表。因此,就該主題提出的另一個解決方案是使用protobuf-net。所以我試過並使用nuget軟件包安裝程序進行安裝。而結束了這個功能(從溶液中Fastest way to serialize and deserialize .NET objects複製)

public static byte[] Serialize(List<Vector> tData) 
{ 
    using (var ms = new MemoryStream()) 
    { 
     ProtoBuf.Serializer.Serialize(ms, tData); 
     return ms.ToArray(); 
    } 
} 

public static List<Vector> Deserialize(byte[] tData) 
{ 
    using (var ms = new MemoryStream(tData)) 
    { 
     return ProtoBuf.Serializer.Deserialize<List<Vector>>(ms); 
    } 
} 

但在運行代碼會導致我上面(標題)所述的錯誤。

我認爲會發生錯誤的:ProtoBuf.Serializer.Serialize(ms, tData);

+0

這裏的'Vector'是什麼樣的? protobuf-net中的類型可以在運行時配置,但我需要一些線索來看看它是什麼樣的......例如nuget上的庫是否可用? –

+0

這是你的'Leap.Vector'嗎? https://developer.leapmotion.com/documentation/csharp/api/Leap.Vector.html如果是這樣,一個相同的解決方案來自[無序列化器爲類型定義:System.Windows.Media.Media3D.Point3D](https ://stackoverflow.com/q/33495897/3744182)應該工作。 – dbc

+0

我懷疑*你需要的是:'RuntimeTypeModel.Default.Add(typeof(Vector),false).Add(「X」,「Y」,「Z」);'在應用程序開始的某個地方,它將開始工作。很高興推斷出類似元組類型的契約,但在這種情況下,我認爲還有一些額外的計算屬性讓它感到困惑(不知道如何將計算出的屬性映射到構造函數)。不過,很難說不訪問'Vector'。 @dbc鏈接到的替代方法是另一種選擇。 –

回答

0

@dbc已經鏈接到類似的代碼重新Point3D,但我不知道這裏需要任何串行器。這看起來很簡單,只是做原料(請注意,我認爲float是這裏的基礎數據類型;如果沒有,只是改變所有sizeof(float)float*爲正確的類型):

static unsafe byte[] Serialize(List<Vector> vectors) 
{ 
    var arr = new byte[3 * sizeof(float) * vectors.Count]; 
    fixed(byte* ptr = arr) 
    { 
     var typed = (float*)ptr; 
     foreach(var vec in vectors) 
     { 
      *typed++ = vec.X; 
      *typed++ = vec.Y; 
      *typed++ = vec.Z; 
     } 
    } 
    return arr; 
} 
static unsafe List<Vector> Deserialize(byte[] arr) 
{ 
    int count = arr.Length/(3 * sizeof(float)); 
    var vectors = new List<Vector>(count); 
    fixed (byte* ptr = arr) 
    { 
     var typed = (float*)ptr; 
     for(int i = 0; i < count; i++) 
     { 
      var x = *typed++; 
      var y = *typed++; 
      var z = *typed++; 
      vectors.Add(new Vector(x, y, z)); 
     }    
    } 
    return vectors; 
} 

如果你真的勇敢,你也可以嘗試直接傾銷底層數據,而不是手動複製字段;如果sizeof(Vector)恰好爲3 * sizeof(float)(或任何基礎類型),那麼這將值得一試。

+0

我很抱歉遲到的回覆先生,並感謝您的即時回覆。上面的代碼工作得非常好!小心解釋這些功能是如何工作的。這仍然是我第一次遇到不安全的代碼。爲什麼這個過程根本不需要任何序列化? – Neelneel

+0

@Neelneel顯示的代碼是* serialization;我所做的一點是,您可能不需要整個序列化庫用於此場景。如果我們看一下'Serialize'方法,它做的是:創建一個所需大小的新數組(每個矢量3個值);獲得一個臨時固定的指針,指向數組的數據(這將是一個'byte *'指針);將它強制爲一個「float *」指針 - 本質上是指「該指針:就像它是指向」浮點數據「的指針;那麼我們遍歷這些值,並且對於每個我們按照該順序寫出X,Y,Z值; (2第1部分) –

+0

@Neelneel的'*鍵入++ = {一些值};'是非常微妙 - '*類型= {一些值}'本身將是「分配{一些值}對存儲器由指向指針'鍵入'「 - 即」將'寫入'typed'「; '鍵入++'本身就是「按照預期的大小增加指針」,即「向前移動一個float,所以它指向下一個空間」。放在一起,他們在一個操作中完成所有這些操作,注意'鍵入的++'是**後** - 增量,因此我們將'X'等寫入**舊**位置,而不是**新**位置。所以:這寫了3個值,我們進一步結束了12個字節;合理? –

相關問題