当我运行显示的单元测试时,我在protobuf 反序列化期间得到异常Object does not match target type
。
我将问题缩小到默认构造函数ContainerForA()
。
这个默认构造函数在反序列化期间用PropA
实例初始化变量ClassA
,因为protobuf-net将调用默认构造函数。然后protobuf反序列化器应该使用序列化的ClassB
实例覆盖此属性。我想在这一点上会抛出异常。
如果我从默认构造函数ContainerForA()
中删除代码,则测试似乎有效。
protobuf-net是否对您在默认构造函数中允许执行的操作有限制?或者我的代码还有其他问题吗?
我正在使用protobuf-net portable 2.0.0.668
[ProtoContract]
[ProtoInclude(101, typeof(IBaseB))]
[ProtoInclude(102, typeof(ClassA))]
public interface IBaseA { }
[ProtoContract]
[ProtoInclude(103, typeof(ClassB))]
public interface IBaseB : IBaseA { }
[ProtoContract]
public class ClassA : IBaseA
{
[ProtoMember(1)]
public int PropA { get; set; }
}
[ProtoContract]
public class ClassB : IBaseB
{
[ProtoMember(2)]
public string PropB { get; set; }
}
[ProtoContract]
public class ContainerForA
{
[ProtoMember(3)]
public IBaseA InstanceOfA { get; set; }
public ContainerForA()
{
InstanceOfA = new ClassA();
}
}
[TestClass]
public class ProtoTestBed1
{
[TestMethod]
public void TestProto()
{
var containerForA = new ContainerForA()
{
InstanceOfA = new ClassB { PropB = "I'm B"}
};
var proto = new ProtobufSerializer();
var bytes = proto.Serialize(containerForA);
var containerForADeserialized = proto.Deserialize<ContainerForA>(bytes);
Debug.WriteLine(containerForADeserialized);
}
}
答案 0 :(得分:3)
我不确定这些约束是什么(马克可能会稍微说一下并告诉你)但是有一些解决方法
试试这个:
[ProtoContract(SkipConstructor=true)]
public class ContainerForA
{
[ProtoMember(3)]
public IBaseA InstanceOfA { get; set; }
public ContainerForA()
{
InstanceOfA = new ClassA();
}
}
使用Portable版本再看看这个。不确定如何使用属性执行此操作,但提出了以下解决方案,似乎通过使用工厂方法来工作&#34;撤消&#34;构造函数。
public class ContainerForA
{
public IBaseA InstanceOfA { get; set; }
public ContainerForA()
{
InstanceOfA = new ClassA();
}
private static ContainerForA EmptyContainerFactory()
{
return new ContainerForA()
{
InstanceOfA = null
};
}
}
static void Main(string[] args)
{
var containerForA = new ContainerForA()
{
InstanceOfA = new ClassB { PropB = "I'm B" }
};
var model = RuntimeTypeModel.Create();
var baseA = model.Add(typeof(IBaseA), true);
baseA.AddSubType(101, typeof(IBaseB));
baseA.AddSubType(102, typeof(ClassA));
var baseB = model.Add(typeof(IBaseB), true);
baseB.AddSubType(103, typeof(ClassB));
var classA = model.Add(typeof(ClassA), true);
classA.AddField(1, "PropA");
var classB = model.Add(typeof(ClassB), true);
classB.AddField(2, "PropB");
var container = model.Add(typeof(ContainerForA), true);
container.AddField(3, "InstanceOfA");
container.SetFactory("EmptyContainerFactory");
MemoryStream mem = new MemoryStream();
model.Serialize(mem, containerForA);
mem.Seek(0, SeekOrigin.Begin);
var containerForADeserialized = model.Deserialize(mem, null, typeof(ContainerForA));
Debug.WriteLine(containerForADeserialized);
}
答案 1 :(得分:0)
项目维护者Marc Gravell证实这是预期的行为:
Protobuf-net不愿意替换实例;
如果子对象/集合/ etc为非null,则会非常难以使用它,而不是重新分配树中的所有内容。
在您的情况下,最简单的修复可能只是在反序列化期间不运行构造函数