protobuf-net: некорректное исключение проводного типа при десериализации свойств Guid - PullRequest
1 голос
/ 10 апреля 2010

У меня проблемы с десериализацией определенных свойств Guid сгенерированных ORM сущностей с использованием protobuf-net.

Вот упрощенный пример кода (воспроизводит большинство элементов сценария, но не воспроизводит поведение; я не могу раскрыть наши внутренние сущности, поэтому я ищу подсказки для объяснения исключения). Скажем, у меня есть класс Account с AccountID направляющей только для чтения и AccountName строкой для чтения и записи. Я сериализую и немедленно десериализирую клон.

Десериализация генерирует исключение Incorrect wire-type deserializing Guid при десериализации.

Вот пример использования ...

        Account acct = new Account() { AccountName = "Bob's Checking" };
        Debug.WriteLine(acct.AccountID.ToString());
        using (MemoryStream ms = new MemoryStream())
        {
            ProtoBuf.Serializer.Serialize<Account>(ms, acct);
            Debug.WriteLine(Encoding.UTF8.GetString(ms.GetBuffer()));
            ms.Position = 0;
            Account clone = ProtoBuf.Serializer.Deserialize<Account>(ms);
            Debug.WriteLine(clone.AccountID.ToString());
        }

А вот пример класса ORM (упрощенный, но демонстрирующий соответствующую семантику, о которой я могу думать). Использует игру-оболочку для десериализации свойств, доступных только для чтения, путем выставления поля поддержки («не могу писать», по сути, становится «не надо писать»), но мы можем сканировать код на наличие примеров присвоения этим полям, поэтому взлом работает для нашего цели).

Опять же, это не воспроизводит поведение исключения; Я ищу подсказки относительно того, что может :

[DataContract()]
[Serializable()]
public partial class Account
{
    public Account()
    {
        _accountID = Guid.NewGuid();
    }
    [XmlAttribute("AccountID")]
    [DataMember(Name = "AccountID", Order = 1)]
    public Guid _accountID;

    /// <summary>
    /// A read-only property; XML, JSON and DataContract serializers all seem
    /// to correctly recognize the public backing field when deserializing: 
    /// </summary>
    [IgnoreDataMember]
    [XmlIgnore]
    public Guid AccountID
    {
        get { return this._accountID; }
    }

    [IgnoreDataMember]
    protected string _accountName;

    [DataMember(Name = "AccountName", Order = 2)]
    [XmlAttribute]
    public string AccountName
    {
        get { return this._accountName; }
        set { this._accountName = value; }
    }
}

Сериализаторы XML, JSON и DataContract, кажется, все отлично сериализуют / десериализуют эти графы объектов, поэтому расположение атрибутов в основном работает. Я пробовал protobuf-net со списками и единичными экземплярами, разными стилями префиксов и т. Д., Но при десериализации всегда получаю исключение «неправильный проводной тип ... Guid».

Итак, конкретные вопросы: есть ли известное объяснение / обходной путь для этого? Я затрудняюсь понять, какие обстоятельства (в реальном коде, но не в примере) могут быть причиной этого.

Мы надеемся , что нам не нужно создавать зависимость protobuf непосредственно на уровне сущностей; в этом случае мы, вероятно, создадим прокси-объекты DTO со всеми открытыми свойствами, имеющими атрибуты protobuf. (Это субъективная проблема, которую я имею со всеми декларативными моделями сериализации; это вездесущий шаблон, и я понимаю, почему он возник, но IMO, если мы можем отправить человека на Луну, тогда «нормальным» должно быть наличие объектов и контрактов сериализации развязан. ;-))

Спасибо!

1 Ответ

1 голос
/ 10 апреля 2010

Согласен, вам не нужна явная зависимость - DataMember в порядке. И protobuf-net использует ту же логику повторного игнорирования и т. Д. Как / где вы храните данные? По моему опыту, наиболее частой причиной этого является то, что люди перезаписывают буфер (или файл) другими данными, а не обрезают его (оставляя мусор в конце потока), , как обсуждалось здесь, Это связано с вашим сценарием?

...