Domanda

A seguito di questa domanda , quale sarebbe il modo migliore per rappresentare un oggetto System.Decimal in un buffer di protocollo?

È stato utile?

Soluzione

Bene, protobuf-net sarà semplicemente gestire questo per voi; Si corre al largo delle proprietà dei tipi, e ha il pieno supporto per decimal. Dal momento che non esiste un modo diretto di esprimere <=> in proto, non sarà (al momento) generano una proprietà <=> da un file "Proto", ma sarebbe un bel tweak per riconoscere alcuni tipo comune ( "BCL .Decimal" o simili) e interpretarlo come decimale.

Per quanto riguarda lo rappresenta - ho avuto un documento di discussione su questo (ora fuori moda ho il sospetto) nella zona wiki protobuf-net; v'è ora una versione funzionante in protobuf-net che semplicemente lo fa per te.

Non c'è dubbio che Jon ed io martello questo fuori più tardi oggi ;-p

La versione protobuf-net di questo (in Proto) è qualcosa di simile (da qui ):

message Decimal {
  optional uint64 lo = 1; // the first 64 bits of the underlying value
  optional uint32 hi = 2; // the last 32 bis of the underlying value
  optional sint32 signScale = 3; // the number of decimal digits, and the sign
}

Altri suggerimenti

Marc e ho piani molto vaghi per trovare una libreria "messaggio comune PB" in modo tale che si può rappresentare tipi abbastanza comuni (data / ora e decimali balzando immediatamente in mente) in un modo comune, con conversioni disponibili in. NET e Java (e qualsiasi altra cosa a chiunque voglia contribuire).

Se sei felice di attenersi a .NET, e siete alla ricerca di compattezza, mi piacerebbe eventualmente andare con qualcosa come:

message Decimal {

    // 96-bit mantissa broken into two chunks
    optional uint64 mantissa_msb = 1;
    optional uint32 mantissa_lsb = 2;

    required sint32 exponent_and_sign = 3;
}

Il segno può semplicemente essere rappresentato dal segno di exponent_and_sign, con l'esponente di essere il valore assoluto.

Fare due parti della mantissa opzionale significa che 0 è rappresentato molto compatto (ma ancora differenziazione tra 0m e 0.0000m ecc). exponent_and_sign potrebbe essere facoltativo e se volevamo.

Non so sul progetto di Marc, ma nella mia porta genero classi parziali, in modo da poter mettere la conversione tra uno System.Decimal e Protobuf.Common.Decimal (o qualsiasi altra cosa) nella classe parziale.

Ho messo insieme un patch per protobuf-csharp porte con ganci che genera le classi protobuf con decimale nativa e le strutture DateTime. formato Wire saggio, essi sono rappresentati da due messaggi proto "built-in".

Ecco il link: https://code.google.com/p/protobuf-csharp-port/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status % 20Priority% 20Milestone% 20Owner% 20Summary & groupby = & sort = & id = 78

A leggermente più semplice per implementare approccio di Jon o Marc consiste nel memorizzare come 4 sint32 valori che mappa banalmente all'uscita di Decimal.GetBits () .

Il file proto sarà simile a:

message ProtoDecimal {
    sint32 v1 = 1;
    sint32 v2 = 2;
    sint32 v3 = 3;
    sint32 v4 = 4;
}

E il convertitore sarà:

public decimal ConvertToDecimal(AbideDecimal value)
{
    return new decimal(new int[] { value.V1, value.V2, value.V3, value.V4 });
}

public ProtoDecimal ConvertFromDecimal(decimal value)
{
    var bits = decimal.GetBits(value);
    return new ProtoDecimal 
    {
        V1 = bits[0],
        V2 = bits[1],
        V3 = bits[2],
        V4 = bits[3]
    }
}

Questo potrebbe non essere così semplice in altre lingue, ma se hai solo di indirizzare C #, allora ci vorrà lo stesso massimo di 16 byte che l'altro approccio (anche se valori come 0 potrebbe non essere memorizzato come compatto - I non so abbastanza circa gli intricati dettagli di come protobuf negozi interi), pur essendo molto più chiaro per i programmatori muto-muti come me :)

Ovviamente si dovrà correre i cavalli se si desidera le prestazioni di prova ma dubito c'è molto in esso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top