protobuf-net: incorrect wire-type exception deserializing Guid properties
- by Paul Smith
I'm having issues deserializing certain Guid properties of ORM-generated entities using protobuf-net.
Here's a simplified example of the code (reproduces most elements of the scenario, but doesn't reproduce the behavior; I can't expose our internal entities, so I'm looking for clues to account for the exception). Say I have a class, Account with an AccountID read-only guid, and an AccountName read-write string. I serialize & immediately deserialize a clone.
Deserializing throws an Incorrect wire-type deserializing Guid exception while deserializing.
Here's example usage...
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());
}
And here's an example ORM'd class (simplified, but demonstrates the relevant semantics I can think of). Uses a shell game to deserialize read-only properties by exposing the backing field ("can't write" essentially becomes "shouldn't write," but we can scan code for instances of assigning to these fields, so the hack works for our purposes).
Again, this does not reproduce the exception behavior; I'm looking for clues as to what could:
[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 and DataContract serializers all seem to serialize / deserialize these object graphs just fine, so the attribute arrangement basically works. I've tried protobuf-net with lists vs. single instances, different prefix styles, etc., but still always get the 'incorrect wire-type ... Guid' exception when deserializing.
So the specific questions is, is there any known explanation / workaround for this? I'm at a loss trying to trace what circumstances (in the real code but not the example) could be causing it.
We hope not to have to create a protobuf dependency directly in the entity layer; if that's the case, we'll probably create proxy DTO entities with all public properties having protobuf attributes. (This is a subjective issue I have with all declarative serialization models; it's a ubiquitous pattern & I understand why it arose, but IMO, if we can put a man on the moon, then "normal" should be to have objects and serialization contracts decoupled. ;-) )
Thanks!