je5real / protobuf-net

Automatically exported from code.google.com/p/protobuf-net
Other
0 stars 0 forks source link

The type cannot be changed once a serializer has been generated #229

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
    [ProtoContract]
    [ProtoInclude(1, typeof(A))]
    interface IA { }

    [ProtoContract]
    class A : IA { }

    [ProtoContract]
    class C
    {
        [ProtoMember(1)]
        internal A A;

        [ProtoMember(2)]
        internal IA IA;
    }

    [ProtoContract]
    class D 
    {
        [ProtoMember(1)]
        internal A A;
        [ProtoMember(2)]
        internal C C;
    }

  MemoryStream memoryStream = new MemoryStream();
  ProtoBuf.Serializer.Serialize<D>(memoryStream, d);
  memoryStream.Position = 0;
  object deserialized2 = ProtoBuf.Serializer.Deserialize<D>(memoryStream);

What is the expected output? What do you see instead?
Expected: The serialization/deserialization should work.
Actual: [The type cannot be changed once a serializer has been generated for 
ProtoBufTest.A] exception is being thrown.

What version of the product are you using? On what operating system?
rev. 444

Please provide any additional information below.
It seems that A metatype is still frozen by the moment C serializer is being 
built and subtype A is added for IA interface.
(line: 73, MetaType.cs:  derivedMeta.ThrowIfFrozen();)

Original issue reported on code.google.com by alexandr...@gmail.com on 5 Sep 2011 at 8:04

GoogleCodeExporter commented 9 years ago
C type does not need to have A field. Is enough to have only IA field. Maybe 
this will simplify the testing scenario.

Original comment by alexandr...@gmail.com on 5 Sep 2011 at 8:07

GoogleCodeExporter commented 9 years ago
I shall investigate

Original comment by marc.gravell on 5 Sep 2011 at 12:51

GoogleCodeExporter commented 9 years ago
I hit this too. It seems if I serialize the concrete class first, I cannot 
serialize the interface that the concrete class implements afterwards. The 
following code shows the problem. The problem goes away if I switch the order 
of serialization (i.e. serialize T first and Foo second).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProtoBuf;
using System.IO;

namespace ProtoBufTest
{
    [ProtoContract, ProtoInclude(100, typeof(Foo))]
    public interface IFoo
    {
        int A { get; }
    }

    [ProtoContract]
    public struct Foo : IFoo
    {
        [ProtoMember(1)]
        public int a;

        public Foo(int a)
        {
            this.a = a;
        }

        public int A
        {
            get
            {
                return a;
            }
        }
    }

    [ProtoContract]
    public class T
    {
        [ProtoMember(1)]
        public IFoo f;
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                Foo f = new Foo(3);
                Serializer.Serialize(ms, f);
            }

            using (MemoryStream ms = new MemoryStream())
            {
                T t = new T();
                t.f = new Foo(2);
                Serializer.Serialize(ms, t);
            }
        }
    }
}

Original comment by MingyuT...@gmail.com on 25 Sep 2012 at 6:53