2011-05-04 58 views
8

我的類屬性具有將被序列化的默認值。c#中的XML序列化和DefaultValue(「」)相關的問題

public class DeclaredValue 
{ 
    [XmlElement(ElementName = "Amount", DataType = "double", IsNullable = false), DefaultValue(999)] 
    public double Amount { get; set; } 

    [XmlElement(ElementName = "Reference2", DataType = "string", IsNullable = false), DefaultValue("")] 
    public string Reference2 { get; set; } 
} 

因此,我們創建了DeclaredValue類的實例併爲Reference2屬性提供了值,並且不爲Amount指定任何值。所以當我們序列化類DeclaredValue然後沒有標籤在我的xml中找到了數量。我提到數量「999」的默認值,那麼爲什麼它不能在序列化中工作。我希望如果不分配任何金額,那麼amoun標籤應該在我的XML默認值。

要做到這一點我需要什麼方式來裝飾數量屬性,它總是帶有默認值在xml序列化後,如果用戶不分配任何東西給這個屬性。

請指導我需要在代碼中更改以獲得所需的輸出。

回答

15

note on MSDN

甲DefaultValueAttribute將原因 一個構件以與該屬性的值 自動 初始化。您必須在代碼中設置初始值 。

有點令人驚訝的是,DefaultValue只調節對象的寫入,等於它們的DefaultValue的成員不會被寫出。

您必須在加載之前或之後初始化成員,例如在構造函數中。

+0

如果我明確地設置了值,那麼DefaultValue會做什麼。你的鏈接不存在....所以給我一個小代碼。 – Mou 2011-05-04 11:59:13

+2

你很可能需要一個構造函數來設置默認值。 – 2011-05-04 12:03:10

+1

在反序列化填充屬性之前調用構造函數。 – Aliostad 2011-08-09 09:44:00

1

正如Henk Holterman所說,此屬性不會自動設置默認值。其目的主要是由視覺設計師用來將屬性重置爲默認值。

+0

你會請示例代碼,因爲事情不清楚。 – Mou 2011-05-04 11:23:15

+1

什麼不明確?該屬性不起作用。你只需要在構造函數中初始化屬性。 – 2011-05-04 13:39:06

7

讓我徹底描述發生了什麼。

當調用XmlSerializer Deserialize()方法時,它使用默認構造函數創建一個新對象。它不會將任何DefaultValueAttributes應用於這個對象,因爲假定默認ctor應該「默默無聞」地默認初始化值。從這個角度來看 - 這是合乎邏輯的。

XmlSerializer不會序列化與DefaultValue屬性標記的值相同的成員。從某種角度來看,這種行爲也是由邏輯推動的。

但是當你不初始化構造函數成員和調用反序列化方法,XmlSerializer的看不到相應的XML領域,但看到現場/酒店DefaultValueAttribute,串行剛剛離開這樣的價值(根據假設默認構造函數更好地知道如何初始化一個類「默認」)。你有零。

解決方案 要初始化這些DefaultValueAttributes(有時是非常方便的,以剛剛到位這個初始值),可以使用這種簡單的方法的類成員:

public YourConstructor() 
    { 
     LoadDefaults(); 
    } 

    public void LoadDefaults() 
    { 
     //Iterate through properties 
     foreach (var property in GetType().GetProperties()) 
     { 
      //Iterate through attributes of this property 
      foreach (Attribute attr in property.GetCustomAttributes(true)) 
      { 
       //does this property have [DefaultValueAttribute]? 
       if (attr is DefaultValueAttribute) 
       { 
        //So lets try to load default value to the property 
        DefaultValueAttribute dv = (DefaultValueAttribute)attr; 
        try 
        { 
         //Is it an array? 
         if (property.PropertyType.IsArray) 
         { 
          //Use set value for arrays 
          property.SetValue(this, null, (object[])dv.Value); 
         } 
         else 
         { 
          //Use set value for.. not arrays 
          property.SetValue(this, dv.Value, null); 
         } 
        } 
        catch (Exception ex) 
        { 
         //eat it... Or maybe Debug.Writeline(ex); 
        } 
       } 
      } 
     } 
    } 

這種「公共無效LoadDefaults ()「,可以作爲對象的擴展進行修飾,或者用作輔助類的靜態方法。

0

正如其他人所述,DefaultValue屬性不會初始化屬性。你可以使用一個簡單的循環來設置的所有屬性:

foreach (var property in GetType().GetProperties()) 
    property.SetValue(this, ((DefaultValueAttribute)Attribute.GetCustomAttribute(
     property, typeof(DefaultValueAttribute)))?.Value, null); 

即使?.Value可以返回null,它的工作原理與非可空類型,我測試了這一點。

如果您的屬性中只有少數屬性具有默認值,那麼您應該只設置該值,如果它存在。

如果所有屬性都應該有默認值,請刪除?,以便在您忘記錯誤時出錯。

很可能,數組無法工作,請參閱MajesticRa的解決方案如何處理。