Protobuf-net序列化错误=“生成序列化程序后无法更改类型”

时间:2011-09-07 11:40:08

标签: protobuf-net

以下场景似乎在反序列化中导致Protobuf.net中的异常。我做错了什么吗?有没有办法解决这个问题?

[ProtoContract]
[ProtoInclude(2, typeof(Ant))]
[ProtoInclude(3, typeof(Cat))]
public interface IBeast
{
    [ProtoMember(1)]
    string Name { get; set; }
}

[ProtoContract]
public class Ant : IBeast
{
    public string Name { get; set; }
}

[ProtoContract]
public class Cat : IBeast
{
    public string Name { get; set; }
}

[ProtoContract]
[ProtoInclude(1, typeof(AntRule1))]
[ProtoInclude(2, typeof(AntRule2))]
[ProtoInclude(3, typeof(CatRule1))]
[ProtoInclude(4, typeof(CatRule2))]
public interface IRule<T> where T : IBeast
{
    bool IsHappy(T beast);
}

[ProtoContract]
public class AntRule1 : IRule<Ant>
{
    public bool IsHappy(IAnt beast)
    {
        return true;
    }
}

[ProtoContract]
public class AntRule2 : IRule<Ant>
{
    public bool IsHappy(IAnt beast)
    {
        return true;
    }
}

[ProtoContract]
public class CatRule1 : IRule<Cat>
{
    public bool IsHappy(ICat beast)
    {
        return true;
    }
}

[ProtoContract]
public class CatRule2 : IRule<Cat>
{
    public bool IsHappy(ICat beast)
    {
        return true;
    }
}

public class TestSerialization
{
    public void Serialize()
    {
        var antRules = new List<IRule<Ant>>();
        antRules.Add(new AntRule1());
        antRules.Add(new AntRule2());

        var catRules = new List<IRule<Cat>>();
        catRules.Add(new CatRule1());
        catRules.Add(new CatRule2());

        using (var fs = File.Create(@"c:\temp\antRules.bin"))
        {
            ProtoBuf.Serializer.Serialize(fs, antRules);

            fs.Close();
        }

        using (var fs = File.OpenRead(@"c:\temp\antRules.bin"))
        {
            List<IRule<Ant>> list;
            list = ProtoBuf.Serializer.Deserialize<List<IRule<Ant>>>(fs);

            fs.Close();
        }

        using (var fs = File.Create(@"c:\temp\catRules.bin"))
        {
            ProtoBuf.Serializer.Serialize(fs, catRules);

            fs.Close();
        }

        using (var fs = File.OpenRead(@"c:\temp\catRules.bin"))
        {
            List<IRule<Cat>> list;
            list = ProtoBuf.Serializer.Deserialize<List<IRule<Cat>>>(fs);

            fs.Close();
        }
    }
}

1 个答案:

答案 0 :(得分:3)

最终我怀疑这里的问题是:

    [ProtoContract]
    [ProtoInclude(1, typeof(AntRule1))]
    [ProtoInclude(2, typeof(AntRule2))]
    [ProtoInclude(3, typeof(CatRule1))]
    [ProtoInclude(4, typeof(CatRule2))]
    public interface IRule<T> where T : IBeast

这表示任何TIRule<T>有4个孩子。如果,如果您有多个T,则每个AndRule1 ... CatRule2都有“n”个父母,这样会产生副作用。不错。让我们假设IRule<Ant>有2个蚂蚁规则,依此类推......(毕竟,我怀疑CatRule1实际上是IRule<Ant>的实现)。目前,这只能通过RuntimeTypeModel来表达,因为这些属性始终适用于所有 T

[ProtoContract]
public interface IRule<T> where T : IBeast

// note these are unrelated networks, so we can use the same field-numbers
RuntimeTypeModel.Default[typeof(IRule<Ant>)]
    .AddSubType(1, typeof(AntRule1)).AddSubType(2, typeof(AntRule2));
RuntimeTypeModel.Default[typeof(IRule<Cat>)]
    .AddSubType(1, typeof(CatRule1)).AddSubType(2, typeof(CatRule2));

然后它的工作原理。请注意,配置只需要完成一次,通常是在应用启动时。


考虑到这一点,我可能可能只是在运行时进行测试,而在泛型的情况下,只是忽略任何不适用的 - 我在评估IRule<Dog>时的意思如果他们实施 IRule<Dog>,请考虑具体类型。不过,我仍然有两种想法。