Pergunta

Na sequência esta questão , o que seria a melhor maneira de representar um objeto System.Decimal em um buffer de protocolo?

Foi útil?

Solução

Bem, protobuf-net simplesmente lidar com isso para você; ele é executado fora das propriedades de tipos, e tem suporte completo para decimal. Desde que não há nenhuma maneira direta de expressar decimal em proto, não vai (atualmente) gerar uma propriedade decimal de um arquivo ".proto", mas seria um bom ajuste para reconhecer algum tipo comum ( 'BCL.Decimal' ou similar) e interpretá-lo como decimal.

Como para representá-lo - Eu tinha um discussão documento neste (agora fora de data suspeito) na área wiki da protobuf-net; existe agora uma versão de trabalho em protobuf-net que simplesmente faz isso por você.

Sem dúvida Jon e eu vou martelar isso mais tarde hoje ;-p

A versão protobuf-net deste (em .proto) é algo como (a partir de aqui ):

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
}

Outras dicas

Marc e eu temos planos muito vagos para chegar a uma "mensagem PB comum" biblioteca de tal forma que você pode representar tipos bastante comuns (data / hora e decimais saltando instantaneamente à mente) de uma maneira comum, com conversões disponível em. NET e Java (e qualquer outra coisa que ninguém quer contribuir).

Se você está feliz em cumpri-NET, e você está olhando para a compacidade, eu possivelmente ir com algo como:

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

O sinal pode apenas ser representada pelo sinal de exponent_and_sign, com o expoente sendo o valor absoluto.

Fazer ambas as partes do meio opcional mantissa que 0 é representado muito compacta (mas ainda a diferenciação entre 0m e 0.0000m etc). exponent_and_sign poderia ser opcional, bem como se nós realmente queríamos.

Eu não sei sobre o projeto de Marc, mas na minha porta eu gerar classes parciais, para que possa a colocar uma conversão entre System.Decimal e Protobuf.Common.Decimal (ou qualquer outro) para a classe parcial.

I montar um remendo para Protobuf-csharp-porta com ganchos que gera classes protobuf com estruturas nativas decimais e de data e hora. fio formato sábio, eles são representados por dois "built-in" mensagens proto.

Aqui está o 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

Um pouco mais simples de implementar abordagem do que Jon ou Marc é armazená-lo como 4 valores sint32, que, convenientemente, mapas trivialmente para a saída de Decimal.GetBits () .

O arquivo proto será algo como:

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

E o conversor será:

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

Isto pode não ser tão simples em outras línguas, mas se você só tem que alvo C #, em seguida, ele vai ocupar o mesmo máximo de 16 bytes que a outra abordagem vai (embora valores como 0 pode não ser tão compactamente armazenados - I não sei o suficiente sobre os intrincados detalhes de como lojas protobuf ints), sendo muito mais claro para os programadores dumb-mudos como me :)

Obviamente você terá que corrida os cavalos se você quiser desempenho do teste, mas eu duvido que há muito nele.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top