2

I'm trying to serialize an immutable message that has an immutable base class. However, I'm unable to convince protobuf-serializer to deserialize it to a derived type. In short this test gives me an invalid cast exception (from Base to 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);
        }
    }

}

This exception goes away if I convert Base and Derived to mutable types. Am I doing anything wrong or is it a limitation of protobuf-net?

4

2 に答える 2

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);
            }
        }

    }
于 2012-07-23T15:52:15.010 に答える
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;

私はこれを確認していないことに注意してください-後で確認します。

于 2012-07-23T16:43:48.020 に答える