下面的场景似乎会导致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:tempantRules.bin"))
{
ProtoBuf.Serializer.Serialize(fs, antRules);
fs.Close();
}
using (var fs = File.OpenRead(@"c:tempantRules.bin"))
{
List<IRule<Ant>> list;
list = ProtoBuf.Serializer.Deserialize<List<IRule<Ant>>>(fs);
fs.Close();
}
using (var fs = File.Create(@"c:tempcatRules.bin"))
{
ProtoBuf.Serializer.Serialize(fs, catRules);
fs.Close();
}
using (var fs = File.OpenRead(@"c:tempcatRules.bin"))
{
List<IRule<Cat>> list;
list = ProtoBuf.Serializer.Deserialize<List<IRule<Cat>>>(fs);
fs.Close();
}
}
}
最终我怀疑这里的问题是:
[ProtoContract]
[ProtoInclude(1, typeof(AntRule1))]
[ProtoInclude(2, typeof(AntRule2))]
[ProtoInclude(3, typeof(CatRule1))]
[ProtoInclude(4, typeof(CatRule2))]
public interface IRule<T> where T : IBeast
这表示对于任何T
, IRule<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>
。不过我还是拿不定主意。