4

Protobuf .Net を使用したデシリアライズについて質問があります。XMLSerializer をそれに置き換えようとしていますが、ファイルから単一のフィールドを逆シリアル化する方法が見つかりません。
ファイルが変更されたかどうかの情報が必要です。これは、保存された構造のフィールドの 1 つです。

それは可能ですか?はいの場合、何か助けを求めることはできますか?

よろしく

4

1 に答える 1

4

ほとんどの場合、率直に言って、全体をデシリアライズするだけで済みます。高速になるなどです。ただし、本当に制限したい場合は、いくつかのオプションがあります。

最も簡単な方法は、必要な情報だけを含む小さなモデルを作成することです。したがって、元のモデルに 46 のフィールドがあり、そのうちの 5 つはコレクションなどですVersionが、フィールド 12 にあるものだけが必要な場合は、次のようになります。

[ProtoContract]
public class InsertNameHere {
    [ProtoMember(12)]
    public int Version {get;set;}
}

それを逆シリアル化ます:

var obj = Serializer.Deserialize<InsertNameHere>(source);
int version = obj.Version;

protobuf-net は契約ベースであるため、これは機能します。十分に似ている限り、まったく同じタイプである必要はありません。ただし、より高度なアプローチは、次を使用することProtoReaderです。

int version = 0;
using (var reader = new ProtoReader(source, RuntimeTypeModel.Default, null))
{
    int field;
    bool keepReading = true;
    while ((field = reader.ReadFieldHeader()) > 0 && keepReading)
    {   
        switch (field)
        {
            case 12:
                version = reader.ReadInt32();
                // STOP LOOPING (leaves the stream partly-read)
                keepReading = false;
                break; 
            default:
                reader.SkipField();
                break;
        }
    }
}

上記を使用する理由は、検索を早期に停止できるためです。つまり、フィールド 12 を見つけたらすぐに、ファイルの残りを処理せずにリーダーを強制終了できます。通常、2 番目の方法は、データが大きいことがわかっていて、あまりデータを必要としない場合にのみ使用します。

技術的には protobuf は追加可能な形式であるため、理論的にはファイルの最後に別の「フィールド 12」が存在する可能性があるという点で、わずかな落とし穴があります。仕様では、「最後の値が勝つ」ため、上記の短絡(理論的には)別の答えを与える可能性があります。でも!これが起こる可能性は非常に低く、通常、追加されたメッセージを利用しているかどうかはわかります。これは、ほとんどの人には当てはまりません。

于 2012-09-24T13:54:09.767 に答える