9

MongoDBのシリアル化C#ドライバーのスタックで小数点以下4桁のシフトを使用して、C#Doubleの表現を丸められたInt64に変更したいと思います。つまり、(Double)29.99を(Int64)299900として格納します

これをアプリに対して透過的にしたいと思います。カスタムシリアライザーを見てきましたが、すべてをオーバーライドしてから、フォールバックを使用してタイプをデフォルトに切り替えるのは少し面倒なので、やりたくありません。

RegisterSerializer()では既存のタイプに1つ追加できません。また、BsonDefaultSerializationProviderにはプリミティブシリアライザーの静的リストがあり、プライベートメンバーで内部としてマークされているため、簡単にサブクラス化できません。

DoublesのInt64としてRepresentAsすることも可能であることがわかりますが、これは変換ではなくキャストです。基本的に、両方のシリアル化方向でキャストと変換が必要です。

デフォルトのシリアライザーにカスタムシリアライザーを指定して、独自のシリアライザーの1つをオーバーライドできればいいのですが、それは汚いハックを意味します。

私は本当に簡単な方法を逃していますか?

4

3 に答える 3

24

あなたは間違いなくこれを行うことができます、あなたはただタイミングを正しくする必要があります。ドライバが起動すると、シリアライザは登録されません。シリアライザーが必要な場合は、辞書で検索し、認識しているシリアライザー(つまり、登録されているシリアライザー)を追跡します。辞書で1つが見つからない場合にのみ、どこで入手できるか(シリアル化プロバイダーの呼び出しを含む)を見つけ出し、見つかった場合は登録します。

RegisterSerializerには制限があるため、すでに使用されている既存のシリアライザーを置き換えることはできません。しかし、それはあなたが十分に早くそれをするならばあなたがあなた自身を登録することができないという意味ではありません。

ただし、シリアライザーの登録はグローバル操作であることに注意してください。したがって、doubleのカスタムシリアライザーを登録すると、すべてのdoubleに使用され、予期しない結果が生じる可能性があります。

とにかく、次のようなカスタムシリアライザーを作成できます。

public class CustomDoubleSerializer : BsonBaseSerializer
{
    public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
    {
        var rep = bsonReader.ReadInt64();
        return rep / 100.0;
    }

    public override void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
    {
        var rep = (long)((double)value * 100);
        bsonWriter.WriteInt64(rep);
    }
}

そして、次のように登録します。

BsonSerializer.RegisterSerializer(typeof(double), new CustomDoubleSerializer());

次のクラスを使用してテストできます。

public class C
{
    public int Id;
    public double X;
}

そしてこのコード:

BsonSerializer.RegisterSerializer(typeof(double), new CustomDoubleSerializer());

var c = new C { Id = 1, X = 29.99 };
var json = c.ToJson();
Console.WriteLine(json);

var r = BsonSerializer.Deserialize<C>(json);
Console.WriteLine(r.X);
于 2012-09-28T14:54:54.677 に答える
0

ドライバーのコードの最新版に目を通し、カスタム シリアライザーを設定するための何らかのバックドアがあるかどうかを確認しました。残念ながら何もありません。ドライバーの将来の反復のためにこれを調べる必要があると思われる場合は、プロジェクトのバグトラッカーで問題を開く必要があります (https://jira.mongodb.org/)。

個人的には、私はチケットを開きます。迅速な回避策が必要または必要な場合は、DoubleSerializer をサブクラス化し、新しい動作を実装してから、Reflection を使用してそれをMongoDB.Bson.Serialization.Serializers.DoubleSerializer.__instanceまたはに挿入しますMongoDB.Bson.Serialization.BsonDefaultSerializationProvider.__serializers

于 2012-09-28T08:12:08.560 に答える