3

BinaryFormatter はシリアル化を簡単に処理できます。

private byte[] TokenToBytes(SessionSecurityToken token)
{
    if (token == null)
    {
        return null;
    }

    using (var memoryStream = new MemoryStream())
    {
        var binaryFormatter = new BinaryFormatter();
        binaryFormatter.Serialize(memoryStream, token);
        return memoryStream.ToArray();
    }
}

BinaryFormatter を protobuf-net に置き換えようとしたとき:

using (var memoryStream = new MemoryStream())
{
    Serializer.Serialize(memoryStream, token);
    return memoryStream.ToArray();
}

次の例外が発生します。

型が予期されておらず、コントラクトを推測できません: System.IdentityModel.Tokens.SessionSecurityToken

追加してみました:

RuntimeTypeModel.Default.Add(typeof(SessionSecurityToken), true);

これは例外を通過しますが、ゼロバイト配列を取得します。

SessionSecurityToken をシリアル化するように protobuf-net を適切に構成するにはどうすればよいですか?

反対に、SessionSecurityToken にはパラメーターなしのコンストラクターがありません。

using (var memoryStream = new MemoryStream(tokenAsBytes))
{
    return Serializer.Deserialize<SessionSecurityToken>(memoryStream);
}

ProtoException をスローします。

SessionSecurityToken のパラメーターなしのコンストラクターが見つかりません

BinaryFormatter大騒ぎせずにそれを行うことができます:

using (var memoryStream = new MemoryStream(bytes))
{
    var binaryFormatter = new BinaryFormatter();
    return (SessionSecurityToken)binaryFormatter.Deserialize(memoryStream);
}

SessionSecurityToken を逆シリアル化するように protobuf-net を適切に構成するにはどうすればよいですか?

4

1 に答える 1

4

protobuf-net は、すべてのタイプをシリアル化できるとは主張していません。XmlSerializer実際、ほとんどのシリアライザー ( 、任意の json シリアライザーDataContractSerializerなど)を介してそれをシリアライズするのは非常に困難です。BinaryFormatterシリアライザーの別のカテゴリにあり、この特定のケースでは、ISerializable.GetObjectData(SerializationInfo, StreamingContext).

コンストラクターは厄介者です。実際、protobuf-net はコンストラクターを完全にバイパスできます。この特定のシナリオBinaryFormatterでは、.ctor(SerializationInfo, StreamingContext).

単純なケースでは、protobuf-net は属性またはランタイム オプションを介して構成できます。より複雑なシナリオでは、サロゲートを使用して表現間のマッピングを行うことができますが、この場合は (の実装を見てSessionSecurityToken) 維持したいよりも複雑であることをお勧めします。

ここでは、1 歩か 2 歩後退します。ほとんどのシリアライザーは、実装ではなくデータを操作するように設計されています。また、DTOなどSessionSecurityTokenうまく機能します。ここでの私の強い提案は次のとおりです: it isではなく、 thisが表すものをシリアル化します。ただし、これが既存の複雑なモデルの一部であり、分離するのが非常に難しい場合は、それらのビットを元に戻すことができます。私はこれをテストしていませんが、考慮してください:BinaryFormatter

RuntimeTypeModel.Default.Add(typeof(SessionSecurityToken), false)
        .SetSurrogate(typeof(BinaryFormatterSurrogate<SessionSecurityToken>));

と:

[ProtoContract]
public class BinaryFormatterSurrogate<T>
{
    [ProtoMember(1)]
    public byte[] Raw { get; set; }

    public static explicit operator T(BinaryFormatterSurrogate<T> value)
    {
        if(value==null || value.Raw == null) return default(T);
        using(var ms = new MemoryStream(value.Raw))
        {
            return (T)new BinaryFormatter().Deserialize(ms);
        }
    }
    public static explicit operator BinaryFormatterSurrogate<T>(T value)
    {
        object obj = value;
        if (obj == null) return null;
        using (var ms = new MemoryStream())
        {
            new BinaryFormatter().Serialize(ms, obj);
            return new BinaryFormatterSurrogate<T> { Raw = ms.ToArray() };
        }

    }
}

これは、あるシリアライザーの出力を生データとして別のシリアライザーに埋め込むだけであることに注意してください。幸いなことに、protobuf-net はバイナリの話に満足しているため、これにより顕著なオーバーヘッド (blob のヘッダーと長さのプレフィックスのみ) が追加されることはありませんが、SessionSecurityTokenインスタンスに対して特にスマートまたは巧妙なことは何もしません。これがシリアライズする唯一のものである場合、それは本当に価値がありません。これが大規模な DTO モデルの 1 つの醜いバンプに過ぎず、そのほとんどが適切にシリアル化できる場合は、それで問題が解決する可能性があります。

于 2013-07-10T07:25:38.400 に答える