2017-07-18 1 views
2

Ich bin dabei, eine Anwendung zu entwickeln, die das Schaltgerät verwendet und mit C# implementiert wird, mein Problem ist, dass ich die Liste speichern möchte, die die Vektoren in meiner Datenbank enthält. Also habe ich über eine Lösung des Transformierens des Vektors in ein Array von Gleitkommazahlen nachgedacht. Das Problem besteht darin, dass jede Liste ein Maximum und ein Minimum von 300 Werten enthält (das Speichern in der Datenbank kostet viel Zeit)."Typ wird nicht erwartet, und kein Vertrag kann abgeleitet werden: Leap.Vector" Fehler. Verwenden von Protobuf-net Serializer

So habe ich nach anderen Möglichkeiten der Speicherung suchen und ich endete auf dem Thema. NET Serialisierung. Ich hatte versucht, die integrierte .net-Serialisierung zu implementieren. Dachte, es hat geklappt, aber noch einmal dauert es ungefähr eine Minute, um die Liste zu serialisieren. Eine andere Lösung, die zu diesem Thema vorgeschlagen wird, ist die Verwendung des Protobuf-Netzes. also habe ich es versucht und installiert mit dem nugget-paketinstallationsprogramm. Und endete mit dieser Funktion nach oben (aus der Lösung kopiert 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); 
    } 
} 

aber den Code ausgeführt wird mich oben (der Titel) angegeben zu dem Fehler führen.

denke ich, wird der Fehler passieren bei: ProtoBuf.Serializer.Serialize(ms, tData);

+0

Wie sieht 'Vector' hier aus? Typen in protobuf-net können zur Laufzeit konfiguriert werden, aber ich brauche einige Hinweise, wie es aussieht ... ist die Bibliothek beispielsweise auf nuget verfügbar? –

+0

Ist das dein 'Leap.Vector'? https://developer.leapmotion.com/documentation/csharp/api/Leap.Vector.html Wenn ja, eine identische Lösung zu der von [Kein Serializer für Typ definiert: System.Windows.Media.Media3D.Point3D] (https : //stackoverflow.com/q/33495897/3744182) sollte funktionieren. – dbc

+0

I * verdächtige * das alles, was Sie brauchen, ist: 'RuntimeTypeModel.Default.Add (typeof (Vector), false) .Add (" X "," Y "," Z ");' irgendwo am Anfang Ihrer App, und es wird anfangen zu arbeiten. Es ist glücklich, Verträge für Tupel-ähnliche Typen abzuleiten, aber in diesem Fall denke ich, dass es einige zusätzliche berechnete Eigenschaften gibt, die es verwirrend machen (nicht zu wissen, wie man die berechneten Eigenschaften dem Konstruktor zuordnen kann). Sehr schwer zu sagen ohne Zugang zu 'Vector'. Der Surrogat-Ansatz, mit dem @dbc verknüpft ist, ist eine weitere Option. –

Antwort

0

@dbc bereits zu ähnlichen Code re Point3D verknüpft hat, aber ich frage mich, ob jede Serializer hier gebraucht wird. Das sieht einfach genug, nur roh tun (beachten Sie, ich bin davon ausgegangen, dass float die zugrunde liegenden Datentyp hier ist, wenn nicht, nur alle sizeof(float) und float* auf den richtigen Typ aus):

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

Wenn Sie sind wirklich mutig, Sie könnten auch versuchen, die zugrunde liegenden Daten direkt Dumping lieber als die Felder manuell kopieren; das wäre einen Versuch wert, wenn sizeof(Vector) genau 3 * sizeof(float) (oder was auch immer der zugrunde liegende Typ ist) ist.

+0

Es tut mir leid für die späte Antwort Sir und danke für die sofortige Antwort. Der obige Code funktioniert prächtig! Es ist wichtig zu erklären, wie diese Funktionen funktionieren. Es ist immer noch das erste Mal, dass ich auf unsichere Codes stoße. Und warum benötigt der Prozess überhaupt keine Serialisierung? – Neelneel

+0

@Neelneel der angezeigte Code * ist * Serialisierung; Der Punkt, den ich gemacht habe, ist, dass Sie wahrscheinlich keine vollständige Serialisierungsbibliothek für dieses Szenario benötigen.Wenn wir uns die "Serialize" -Methode anschauen, machen wir folgendes: Erstellen Sie ein neues Array der benötigten Größe (3 Werte pro Vektor); Erhalte einen temporär angehefteten Zeiger auf die Daten des Arrays (der ein 'byte *' -Zeiger sein wird); erzwinge das in einen 'float *' Zeiger - im Wesentlichen sagend "dieser Zeiger: handle wie ein Zeiger auf' float' Daten "; dann werden die Werte iteriert, und für jedes schreiben wir die X-, Y-, Z-Werte in dieser Reihenfolge; (Teil 1 von 2) –

+0

@Neelneel das '* tippte ++ = {irgendein Wert};' ist sehr subtil - '* typed = {irgendein Wert}' würde selbst "dem Wert, auf den der Zeiger 'typed'" - dh "schreibe' X' in 'getippt'"; 'typed ++' selbst wäre "inkrementiere den Zeiger um seine erwartete Größe" - d. h. "move typed vorwärts um eins" float ", so dass es auf das nächste Leerzeichen zeigt". Zusammengenommen machen sie das alles in einer Operation und stellen fest, dass "typisierte ++" ** post ** - Inkrement ist, also schreiben wir "X" usw. an den ** alten ** Ort, nicht an den ** neuen ** Ort . Also: das schreibt die 3 Werte und wir enden 12 Bytes weiter; Sinn ergeben? –

Verwandte Themen