2

I'm trying to serialize some typesafe enums which I implemented like the answer to this question. When I serialize an object containing a reference to, say, FORMS (from the answer I linked), I'd like, upon deserialization, to restore the reference to the static field FORMS.

I have a solution but it seems kind crappy since I'd have to add it to any class that contained a typesafe enum. It pretty much just uses callbacks to store and retrieve the enum's value field:

    public class SomethingContainingAnAuthenticationMethod
    {
      [ProtoMember(1)] 
      public int AuthenticationMethodDataTransferField { get; set; }

      public AuthenticationMethod AuthenticationMethod { get; set; }

      [ProtoBeforeSerialization]
      public void PopulateDataTransferField()
      {
        AuthenticationMethodDataTransferField = AuthenticationMethod.value;
      }

      [ProtoAfterDeserialization]
      public void PopulateAuthenticationMethodField()
      {
        AuthenticationMethod = AuthenticationMethod.FromInt(AuthenticationMethodDataTransferField);
      }
    }

Any other ideas would be much appreciated.

Community
  • 1
  • 1
jjfine
  • 889
  • 7
  • 20
  • You could try implementing ISerializable on the type-safe enum class. Or even better you could create a base class for all of your type-safe enum classes and implement ISerializable on the base class. Of course you should add the SerializableAttribute to each type-safe enum class. Another thing to note is equality tests. You need value equality instead of reference equality (http://msdn.microsoft.com/en-us/library/dd183755.aspx). – Panos Rontogiannis Nov 10 '12 at 00:43
  • K; can you clarify a few things? An enum should serialize just fine without any work - what happens if you *just* mark the enum member with ProtoMember? What is the symptom you're trying to avoid? Also: you mention "static field" - do you actually mean `static`, as in "type-specific, not instance-specific"? Or...? – Marc Gravell Nov 10 '12 at 08:00
  • @Panos the example suggests the OP is talking about protobuf-net, to which none of that applies. – Marc Gravell Nov 10 '12 at 08:01
  • @MarcGravell jjfine is not trying to serialize .NET enums. He wants to implement Java's type-safe enum pattern, which includes a private constructor and public static fields for each enum value. How is he going to test for equality against these static fields without implementing IEquatable? By the way protobuf-net is very interesting. Efficiency and interoperability all in one! – Panos Rontogiannis Nov 11 '12 at 19:56
  • @Panos the **question** in the example linked to **is** a regular .NET `enum`. I'm happy to help, but I'd need a proper example of the scenario. I'm immediately thinking "via a surrogate" (just one of the many options available) - but: I'd need an actual genuine example that matches what the OP is doing. – Marc Gravell Nov 11 '12 at 20:06

2 Answers2

2

With the answer in the linked example, the simplest approach is probably:

[ProtoContract]
public class SomethingContainingAnAuthenticationMethod
{
  [ProtoMember(1)] 
  private int? AuthenticationMethodDataTransferField {
      get { return AuthenticationMethod == null ? (int?)null
                               : AuthenticationMethod.Value; }
      set { AuthenticationMethod = value == null ? null
                               : AuthenticationMethod.FromInt(value.Value); }
  }

  public AuthenticationMethod AuthenticationMethod { get; set; }
}

which avoids an extra field and any callbacks. Something similar could also be done via a surrogate-type, but the above should work for most simple cases.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
1

The mechanism for serializing an enum member is pretty simple:

[ProtoContract]
public class SomethingContainingAnAuthenticationMethod
{
    [ProtoMember(1)] 
    public AuthenticationMethod AuthenticationMethod { get; set; }
}

And... that's about it. The minor gotcha sometimes (which might raise errors about not being able to find an enum with value) is the implicit-zero behaviour, but that is simply avoided:

    [ProtoMember(1, IsRequired=true)] 
    public AuthenticationMethod AuthenticationMethod { get; set; }
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900