2015-10-13 14 views
4

我用Json.Net排查(德)序列化問題與下面的類:Json.Net反序列化構造對產權規則

public class CoinsWithdrawn 
{ 
    public DateTimeOffset WithdrawlDate { get; private set; } 
    public Dictionary<CoinType, int> NumberOfCoinsByType { get; private set; } 

    public CoinsWithdrawn(DateTimeOffset withdrawDate, Dictionary<CoinType, int> numberOfCoinsByType) 
    { 
     WithdrawlDate = withdrawDate; 
     NumberOfCoinsByType = numberOfCoinsByType; 
    } 
} 

的問題是,構造函數參數「withdrawDate」的名稱不同比屬性名稱「WithDrawlDate」。使名稱匹配(即使忽略大小寫)解決了問題。

但是,我想更好地理解這一點,所以在公佈兩個setter之後,我恢復了代碼並進行了測試。這也解決了這個問題。

最後,我從自動性切換到性能與支持字段,這樣我可以充分的調試,看看究竟是怎麼回事:

public class CoinsWithdrawn 
{ 
    private DateTimeOffset _withdrawlDate; 
    private Dictionary<CoinType, int> _numberOfCoinsByType; 

    public DateTimeOffset WithdrawlDate 
    { 
     get { return _withdrawlDate; } 
     set { _withdrawlDate = value; } 
    } 

    public Dictionary<CoinType, int> NumberOfCoinsByType 
    { 
     get { return _numberOfCoinsByType; } 
     set { _numberOfCoinsByType = value; } 
    } 

    public CoinsWithdrawn(DateTimeOffset withdrawDate, Dictionary<CoinType, int> numberOfCoinsByType) 
    { 
     WithdrawlDate = withdrawDate; 
     NumberOfCoinsByType = numberOfCoinsByType; 
    } 
} 

我想這與不顯示默認構造函數(代碼省略默認構造函數)。

使用默認構造函數:調用默認構造函數,然後調用兩個屬性設置器。

沒有默認構造函數:調用非默認構造函數,然後調用WithDrawlDate設置器。 NumberOfCoinsByType setter永遠不會被調用。

我最好的猜測是反序列化器跟蹤哪些屬性可以通過構造函數設置(通過一些約定,因爲套管似乎被忽略),然後使用屬性設置器填充空位。

這是它的工作方式?反序列化操作/規則的順序是否記錄在某處?

回答

2

我最好的猜測是反序列化器跟蹤哪些屬性可以通過構造函數設置(通過一些約定,因爲套管似乎被忽略),然後使用屬性設置器填充空位。 這是它的工作方式?

是的,這幾乎是要點。如果你看看source code,你可以親眼看到。在JsonSerializerInternalReader類中有一個方法CreateObjectUsingCreatorWithParameters,它使用非默認構造函數處理對象的實例化。我已經複製下面的相關位。

ResolvePropertyAndCreatorValues方法從JSON獲取數據值,然後循環嘗試將它們匹配到構造函數參數。那些不匹配被添加到remainingPropertyValues字典。然後使用匹配的參數對對象進行實例化,使用null /默認值填充任何空白。稍後在方法中的第二個循環(此處未顯示)然後嘗試針對該字典中的其餘屬性調用對象上的setter。

IDictionary<JsonProperty, object> propertyValues = 
    ResolvePropertyAndCreatorValues(contract, containerProperty, reader, objectType, out extensionData); 

object[] creatorParameterValues = new object[contract.CreatorParameters.Count]; 
IDictionary<JsonProperty, object> remainingPropertyValues = new Dictionary<JsonProperty, object>(); 

foreach (KeyValuePair<JsonProperty, object> propertyValue in propertyValues) 
{ 
    JsonProperty property = propertyValue.Key; 

    JsonProperty matchingCreatorParameter; 
    if (contract.CreatorParameters.Contains(property)) 
    { 
     matchingCreatorParameter = property; 
    } 
    else 
    { 
     // check to see if a parameter with the same name as the underlying property name exists and match to that 
     matchingCreatorParameter = contract.CreatorParameters.ForgivingCaseSensitiveFind(p => p.PropertyName, property.UnderlyingName); 
    } 

    if (matchingCreatorParameter != null) 
    { 
     int i = contract.CreatorParameters.IndexOf(matchingCreatorParameter); 
     creatorParameterValues[i] = propertyValue.Value; 
    } 
    else 
    { 
     remainingPropertyValues.Add(propertyValue); 
    } 

    ... 
} 
... 

object createdObject = creator(creatorParameterValues); 

... 

參數匹配算法本質上是如果有找到多個匹配落在回到是大小寫敏感的情況下不敏感的搜索。如果您有興趣,請查看ForgivingCaseSensitiveFind實用程序方法。

反序列化操作/規則的順序是否記錄在某處?

不是我所知。官方文檔是here,但它沒有涉及到這一級別的細節。