2015-06-17 52 views
0

我有一個字段,它是一個我想要序列化和反序列化的委託。反序列化一個類型爲委託的字段的類

它看起來像這樣:

public delegate bool DistanceEqualityStrategy (Distance distance1, Distance distance2); 

[JsonObject(MemberSerialization.Fields)] 
public partial class Distance 
{ 

    private double _intrinsicValue; 

    [JsonIgnore] 
    private DistanceEqualityStrategy _strategy; 

    public Distance(double passedInput, DistanceEqualityStrategy passedStrategy = null) 
    { 
     _intrinsicValue = passedInput; 
     _equalityStrategy = _chooseDefaultOrPassedStrategy(passedStrategy); 
    } 

    public Distance(Distance passedDistance) 
    { 
     _intrinsicValue = passedDistance._intrinsicValue; 
     _equalityStrategy = passedDistance._equalityStrategy; 
    } 

    private static DistanceEqualityStrategy _chooseDefaultOrPassedStrategy(DistanceEqualityStrategy passedStrategy) 
    { 
     if (passedStrategy == null) 
     { 
      return EqualityStrategyImplementations.DefaultConstantEquality; 
     } 
     else 
     { 
      return passedStrategy; 
     } 
    } 
} 

我無法理解什麼是真的反序列化該對象時打開。對象如何重建?當它嘗試重新創建對象時,它是否調用該類的特定構造函數?它的序列化很好,但是當重建對象時,它將委託設置爲null。

這使我得出結論,我不明白這種反序列化是如何工作的,因爲它似乎沒有使用構造函數。

有人可以向我解釋如何在不使用構造函數的情況下在反序列化中創建對象嗎?

+0

不是最好顯示你的代碼和/或結構等,以便其他人不必實施他們的JetEye心靈力量..? – MethodMan

+3

序列化代表是不可能的。這將如何工作? – SLaks

+2

@SLaks說了什麼:_思考序列化委託會意味着什麼。什麼會通過電線發送?如果委託設置爲「空」,則沒有問題。但是如果委託在序列化代碼中被設置爲類實例的方法呢?這個實例是否也被序列化?如果不是,代表執行時代表什麼意思?正在執行的代碼是否會通過網絡進入您的進程以在您的實例上執行該方法?如果沒有電線怎麼辦?如果代表被序列化成文件會怎麼樣? –

回答

0

我不認爲代表有什麼關係你的問題,這似乎是:

我可以設置標有JsonIgnore屬性字段提供自定義的邏輯是什麼? (因爲它們不包含在序列化流中)

不幸的是,JsonIgnoreAttribute文檔非常稀缺,並沒有解釋這一點。也許它在別處被覆蓋。

至於你關於什麼構造函數被使用的問題,它似乎受到JsonSerializer實例上的ConstructorHandling屬性的控制。

CustomCreationConverter class也聽起來可能是相關的,因爲它被描述爲「提供了一種方法來定製在JSON反序列化期間如何創建對象」。

+0

如果OP同意您的問題並非特定於代表,請與OP一起編輯問題(特別是標題)。 –

+0

我真正的問題是關於反序列化是如何工作的。代表明確表示我的構造函數都沒有被調用 – jth41

0

你問了,有人可以向我解釋如何在不使用構造函數的情況下在反序列化中創建對象嗎?

簡而言之,FormatterServices.GetUninitializedObject()可以用來做這個。

問題中顯示的POCO類型已標記爲[JsonObject(MemberSerialization.Fields)]。將MemberSerialization.Fields應用於maps to a JSON object觸發特殊建築規則的POCO類型。對於Json.NET如何決定如何構建這種類型的實例的規則如下:

  1. 如果[JsonConstructor]被設置在一個構造函數,使用該構造。

  2. 接着,在full trust only,當MemberSerialization.Fields被施加,或[Serializable]被施加並DefaultContractResolver.IgnoreSerializableAttribute == false,特殊方法FormatterServices.GetUninitializedObject()用於分配的對象。 沒有調用該類型的構造函數。

  3. 接下來,如果有一個公共無參數構造函數,請使用它。

  4. 接下來,如果存在非公共無參數構造函數並且使用它。

  5. 接着,如果有一個單公共參數的構造函數,使用該構造,通過名(模時)相匹配的JSON對象屬性來構造參數然後解串匹配的屬性給構造參數類型。當沒有匹配的JSON對象屬性時傳遞默認值。

  6. 如果上述失敗,則無法構造該對象,並且在反序列化過程中會拋出異常。

查看the reference source的邏輯。 Dictionaries,dynamic objects,實現ISerializable,collections的類型(映射到JSON數組的類型)以及映射到JSON基元的類型可能有一些不同的規則。

因此調用FormatterServices.GetUninitializedObject()而不是類型的構造函數,所以它的_equalityStrategy永遠不會被初始化。

作爲一種解決辦法,因爲你沒有序列化_equalityStrategy反正,你可以添加一個OnDeserialized callback初始化它:

[JsonObject(MemberSerialization.Fields)] 
public partial class Distance 
{ 
    [JsonIgnore] 
    private DistanceEqualityStrategy _equalityStrategy; 

    [OnDeserialized] 
    void OnDeserialized(StreamingContext context) 
    { 
     this._equalityStrategy = _chooseDefaultOrPassedStrategy(this._equalityStrategy); 
    } 
} 

Json.NET的這種行爲沒有明確的記載。最相關的段落從Serialization Guide

最後,類型可以使用場模式序列化。所有的公共和私人領域都被序列化,屬性被忽略。這可以通過使用JsonObjectAttribute將TypeSerialization.Fields設置爲類型,或者使用.NET SerializableAttribute並將DefaultContractResolver上的IgnoreSerializableAttribute設置爲false來指定。

而且從Json.NET 4.5 Release 8 release notes

變化 - 串行器現在創建反序列化序列化的類型時使用GetUninitializedObject對象。

實際上,GetUninitializedObject()用於「字段模式」,可能是爲了模仿DataContractJsonSerializer的行爲。如果你喜歡,你可以report a documentation issue