Is it possible to serialize/deserialize immutable types with protobuf-net on Windows Phone 7/8?

c#, immutability, protobuf-net, windows-phone, windows-phone-7

Solution

You can use a surrogate; here I'm decorating it with attributes, but it can be configured manually too:

[ProtoContract]
public class MutablePoint {
    [ProtoMember(1)] public double X { get; set; }
    [ProtoMember(2)] public double Y { get; set; }

    public static implicit operator MutablePoint(ImmutablePoint value) {
        return value == null ? null : new MutablePoint {X=value.X, Y=value.Y};
    }
    public static implicit operator ImmutablePoint(MutablePoint value) {
        return value == null ? null : new ImmutablePoint(value.X, value.Y);
    }
}

and then tell the model to use this whenever it sees `ImmutablePoint`:

var model = TypeModel.Create();
model.Add(typeof(MutablePoint), true);
model.Add(typeof(ImmutablePoint), false).SetSurrogate(typeof(MutablePoint));

The serializer will use the operators to switch between them as necessary. The serializer will use either `implicit` or `explicit` custom conversion operators.

EDIT: Deserialize like this

ImmutablePoint ptDeSer = (ImmutablePoint)model.Deserialize(stream1, null, typeof(ImmutablePoint));

Problem

Is it possible to serialize/deserialize types with protobuf-net on Windows Phone 7/8? I've tried the code below, it seems Constructor skipping isn't supported (i.e. UseConstructor = false) so I created a parameterless constructor but the deserialization fails with "Attempt to access the method failed: Wp7Tests.ImmutablePoint.set_X(System.Double)" ``` public class ImmutablePoint { public double X { get; private set; } public double Y { get; private set; } public ImmutablePoint() {} public ImmutablePoint(double x, double y) { X = x; Y = y; } } public sub Test() { ImmutablePoint pt = new ImmutablePoint(1, 2); var model = TypeModel.Create(); var ptType = model.Add(typeof(ImmutablePoint), false); ptType.AddField(1, "X"); ptType.AddField(2, "Y"); IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication(); using (var stream1 = new IsolatedStorageFileStream("test.bin", FileMode.Create, store)) { try { model.Serialize(stream1, pt); } catch (Exception e) { Debugger.Break(); } } const double EPSILON = 0.001; using (var stream1 = new IsolatedStorageFileStream("test.bin", FileMode.Open, store)) { try { ImmutablePoint ptDeSer = (ImmutablePoint) model.Deserialize(stream1,null, typeof(ImmutablePoint)); Debug.Assert(Math.Abs(pt.X - ptDeSer.X) < EPSILON); Debug.Assert(Math.Abs(pt.Y - ptDeSer.Y) < EPSILON); } catch (Exception e) { Debugger.Break(); } } } ```

Original source