2013-04-17 27 views
3

是否可以在Windows Phone 7/8上使用protobuf-net序列化/反序列化類型?
我試過下面的代碼,它似乎不支持構造函數跳過(即UseConstructor = false),所以我創建了無參數構造函數,但反序列化失敗,「嘗試訪問方法失敗:Wp7Tests.ImmutablePoint.set_X(System .Double)「是否可以在Windows Phone 7/8上使用protobuf-net序列化/反序列化不可變類型?

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(); 
      } 
     } 
} 

回答

7

您可以使用代理;我在這裏用的屬性裝飾它,但它可以配置手動太:

[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); 
    } 
} 

,然後告訴使用這個模型,只要自己認爲ImmutablePoint

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

串行器將使用運營商根據需要在它們之間切換。序列化器將使用implicitexplicit自定義轉換運算符。

編輯: 反序列化這樣

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

這在Windows Phone上不可行。反序列化程序無法訪問setter,並使用反射訪問私有成員,導致Windows Phone上的MemberAccessException。我能想到得到像這樣的東西的唯一方法就是創建一個序列化包裝器,然後調用你的ImmutablePoint的構造器。雖然包裝類需要X和Y的公共讀寫屬性,但這一切都有點麻煩。

您也可以看看使用InternalsVisibleTo屬性允許序列化程序訪問屬性(假設您將設置程序從私人內部)。儘管...仍然凌亂...

+0

那是什麼,我會猜:(我想我可能會添加一個接口說ISerializablePoint暴露在X,Y屬性則明確地實現它們的這不是一個理想的解決方案,但我認爲它傳達了意圖,它隱藏了類的默認界面的可變性 –

+0

@DavidHayes有一個更優雅的方式...答案添加 –

+0

絕對是一個更清潔的方式,謝謝。 – calum

相關問題