我正在尝试序列化具有不可变基类的不可变消息。但是,我无法说服protobuf-serializer将其反序列化为派生类型。简而言之,这个测试给了我一个无效的强制转换异常(从Base到Derived):
[TestFixture]
public class InheritanceTest
{
public class Base
{
public int IntField { get; private set; }
public Base(int intField)
{
IntField = intField;
}
}
public class Derived : Base
{
public string StringField { get; private set; }
public Derived(int intField, string stringField) : base(intField)
{
StringField = stringField;
}
}
[Test]
public void TestInheritance()
{
var serializer = TypeModel.Create();
serializer.Add(typeof (Base), true)
.Add(1, "IntField")
.AddSubType(2, typeof (Derived))
.UseConstructor = false;
serializer.Add(typeof (Derived), true)
.Add(1, "StringField")
.UseConstructor = false;
serializer.CompileInPlace();
using (var stream = new MemoryStream())
{
var message = new Derived(1, "Some text that is not important");
serializer.Serialize(stream, message);
stream.Position = 0;
var retrieved = (Derived) serializer.Deserialize(stream, null, typeof (Derived));
Assert.AreEqual(message.IntField, retrieved.IntField);
Assert.AreEqual(message.StringField, retrieved.StringField);
}
}
}
如果我将Base和Derived转换为可变类型,则此异常消失。我做错了什么或者它是protobuf-net的限制吗?
答案 0 :(得分:1)
[TestFixture]
public class InheritanceTest
{
public class Base
{
public int IntField { get; private set; }
public Base(int intField)
{
IntField = intField;
}
}
public class Derived : Base
{
public string StringField { get; private set; }
public Derived(int intField, string stringField) : base(intField)
{
StringField = stringField;
}
}
[Test]
public void TestInheritance()
{
var serializer = TypeModel.Create();
serializer.Add(typeof (Base), true)
.Add(1, "IntField")
.UseConstructor = false;
serializer.Add(typeof (Derived), true)
.Add(1, "StringField")
.UseConstructor = false;
serializer.CompileInPlace();
using (var stream = new MemoryStream())
{
var message = new Derived(1, "Some text that is not important");
serializer.Serialize(stream, message);
stream.Position = 0;
var retrieved = (Derived) serializer.Deserialize(stream, null, typeof (Derived));
Assert.AreEqual(message.IntField, retrieved.IntField);
Assert.AreEqual(message.StringField, retrieved.StringField);
}
}
}
或
[TestFixture]
public class InheritanceTest
{
[DataContract]
public class Base
{
[DataMember(Order = 1)]
public int IntField { get; private set; }
public Base(int intField)
{
IntField = intField;
}
protected Base(){}
}
[DataContract]
public class Derived : Base
{
[DataMember(Order = 3)]
public string StringField { get; private set; }
public Derived(int intField, string stringField) : base(intField)
{
StringField = stringField;
}
private Derived(){}
}
[Test]
public void TestInheritance()
{
RuntimeTypeModel.Default.Add(typeof(Base), true).AddSubType(2, typeof(Derived));
using (var stream = new MemoryStream())
{
var message = new Derived(1, "Some text that is not important");
Serializer.Serialize(stream, message);
stream.Position = 0;
var retrieved = Serializer.Deserialize<Derived>(stream);
Assert.AreEqual(message.IntField, retrieved.IntField);
Assert.AreEqual(message.StringField, retrieved.StringField);
}
}
}
答案 1 :(得分:0)
这看起来是元组检测的副作用,导致它具有特定的代码分支。好的是,您应该可以通过将true
更改为false
来解决原始代码中的问题。此参数告诉您是否应用标准行为。您不需要,因为您自己定义模型。
var serializer = TypeModel.Create();
serializer.Add(typeof (Base), false)
.Add(1, "IntField")
.AddSubType(2, typeof (Derived))
.UseConstructor = false;
serializer.Add(typeof (Derived), false)
.Add(1, "StringField")
.UseConstructor = false;
注意我还没有证实这一点 - 我稍后会检查。