Сбой созданной RuntimeTypeModel во время десериализации сложного объекта

#c# #protobuf-net

#c# #protobuf-net

Вопрос:

Я хотел использовать protocolbuf .net версии без атрибутов, с RuntimeTypeModel, созданной с помощью определенного кода. Это работало довольно хорошо, пока я не попал в дело, которое было извлечено в случае ниже. Версия библиотеки protobuf-net, на которую ссылается protobuf, равна 2.0.0.447. Что не так с созданием этой модели? Какие-либо подсказки?

 public class ProtoBufFailingTest
{
    public abstract class Message
    {
    }

    public class SomeMessage : Message
    {
        public readonly Descriptor Desc;

        public SomeMessage(Descriptor desc)
        {
            Desc = desc;
        }
    }

    public struct Descriptor
    {
        public readonly Event EventData;

        public Descriptor(Event eventData)
        {
            EventData = eventData;
        }
    }

    public abstract class Event
    {
    }

    public class SomeEvent : Event
    {
        public int SomeField;
    }

    [Test]
    public void FailingTest( )
    {
        var model = TypeModel.Create();

        // message hierarchy
        {
            var messages = model.Add(typeof(Message), true);
            messages.AddSubType(1, typeof(SomeMessage));
            model[typeof(SomeMessage)].UseConstructor = false;
        }

        // events hierarchy
        {
            var events = model.Add(typeof (Event), true);
            events.AddSubType(1, typeof (SomeEvent));
            model[typeof (SomeEvent)].UseConstructor = false;
        }

        // descriptor
        var eventDescriptorModel = model.Add(typeof(Descriptor), true);
        eventDescriptorModel.UseConstructor = false;

        var typeModel = model.Compile();

        const PrefixStyle prefixStyle = PrefixStyle.Base128;
        const int testValue = 5;
        using (var ms = new MemoryStream())
        {

            typeModel.SerializeWithLengthPrefix(ms, new SomeMessage(new Descriptor(new SomeEvent { SomeField = testValue })), null, prefixStyle, 0);

            ms.Seek(0, SeekOrigin.Begin);

            // fails here
            var message = (SomeMessage)typeModel.DeserializeWithLengthPrefix(ms, null, typeof(Message), prefixStyle, 0);

            Assert.AreEqual(testValue, ((SomeEvent)message.Desc.EventData).SomeField);
        }
    }
}
  

Комментарии:

1. Извините, я как-то пропустил это вчера. Я далеко от своего компьютера, но подготовлю ответ на это позже, когда вернусь.

2. Жду вашего ответа. Будьте осторожны!

3. хм, да, это глупо; посмотрите на это повторно; это ошибка IL emit (переполнение стека), так что в тесте нет ничего плохого (за исключением того, что он не добавляет .SomeField к SomeEvent ‘s MetaType )

4. Теперь это исправлено в r450 ( code.google.com/p/protobuf-net/downloads )

5. Это работает как шарм. Спасибо за самую быструю помощь.

Ответ №1:

Очень просто; в библиотеке есть (была) ошибка, выдающая

 initobj {type}
stloc.0
  

когда очевидно (кашель) для типа значения Descriptor , он должен был выдавать

 ldloca.s 0
initobj {type}
  

Я разверну это, как только проверю, что я ничего не дестабилизировал.