带有ProtoBuf序列化的RedisSessionStateProvider导致错误

时间:2017-05-25 23:35:00

标签: c# redis protobuf-net stackexchange.redis

我正在尝试使用RedisSessionStateProvider进行protobuf序列化。我已将redisSerializerType指定为实现Microsoft.Web.Redis.ISerializer的自定义类 - 这是反序列化代码:

    public object Deserialize(byte[] data)
    {
        return DeserializeDirect(data);
    }

    private object DeserializeDirect(byte[] data)
    {
        using (var memoryStream = new MemoryStream(data))
        {
            return Serializer.Deserialize<object>(memoryStream);
        }
        return null;
    }

由于我需要实现Microsoft.Web.Redis.ISerializer,deserialize的签名使用返回类型的对象,并且无法传入返回的实际类型。因此,当DeserializeDirect尝试使用Protobuf.Serializer对其进行反序列化(如预期的那样)时说“不期望类型,并且不能推断出任何契约:System.Object”。我正在使用.NET框架4.6.1的Web应用程序,我希望有人可以指出我做错了什么。

谢谢!

1 个答案:

答案 0 :(得分:1)

通常,protobuf-net 确实想知道确切的类型。但是,您可以使用DynamicType作弊。这告诉protobuf-net包含其他类型的元数据 - 它通常不包括。

请注意,这可能会使代码变脆 - 如果代码中的类型发生更改,则可能会失败!

我将很快实施Any(作为2.3.0的一部分),这是另一种选择。

public static void Main()
{
    // the actual object we care about
    object obj = new Foo { X = 1 };

    // serialize and deserialize via stub
    var stub = new Stub { Data = obj };
    var clone = Serializer.DeepClone(stub);
    // prove it worked
    Console.WriteLine(clone.Data);
    // prove it is a different instance
    Console.WriteLine(ReferenceEquals(obj, clone.Data));
}
[ProtoContract]
public class Foo
{
    [ProtoMember(1)]
    public int X { get; set; }
    public override string ToString() => $"X={X}";
}

[ProtoContract]
public sealed class Stub
{
    [ProtoMember(1, DynamicType = true)]
    public object Data { get; set; }
}