2012-07-04 57 views
39

XML屬性我有下面的類:序列化屬性在元

[Serializable] 
public class SomeModel 
{ 
    [XmlElement("SomeStringElementName")] 
    public string SomeString { get; set; } 

    [XmlElement("SomeInfoElementName")] 
    public int SomeInfo { get; set; } 
} 

這(與一些測試數據填充)和序列化使用XmlSerializer.Serialize()結果如下XML:

<SomeModel> 
    <SomeStringElementName>testData</SomeStringElementName> 
    <SomeInfoElementName>5</SomeInfoElementName> 
</SomeModel> 

我需要的是:

<SomeModel> 
    <SomeStringElementName Value="testData" /> 
    <SomeInfoElementName Value="5" /> 
</SomeModel> 

有沒有將其指定爲屬性機智的方式豪特寫我自己的自定義序列化代碼?

回答

65

您需要的包裝類:

public class SomeIntInfo 
{ 
    [XmlAttribute] 
    public int Value { get; set; } 
} 

public class SomeStringInfo 
{ 
    [XmlAttribute] 
    public string Value { get; set; } 
} 

public class SomeModel 
{ 
    [XmlElement("SomeStringElementName")] 
    public SomeStringInfo SomeString { get; set; } 

    [XmlElement("SomeInfoElementName")] 
    public SomeIntInfo SomeInfo { get; set; } 
} 

或更通用的方法,如果你喜歡:

public class SomeInfo<T> 
{ 
    [XmlAttribute] 
    public T Value { get; set; } 
} 

public class SomeModel 
{ 
    [XmlElement("SomeStringElementName")] 
    public SomeInfo<string> SomeString { get; set; } 

    [XmlElement("SomeInfoElementName")] 
    public SomeInfo<int> SomeInfo { get; set; } 
} 

然後:

class Program 
{ 
    static void Main() 
    { 
     var model = new SomeModel 
     { 
      SomeString = new SomeInfo<string> { Value = "testData" }, 
      SomeInfo = new SomeInfo<int> { Value = 5 } 
     }; 
     var serializer = new XmlSerializer(model.GetType()); 
     serializer.Serialize(Console.Out, model); 
    } 
} 

會產生:

<?xml version="1.0" encoding="ibm850"?> 
<SomeModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <SomeStringElementName Value="testData" /> 
    <SomeInfoElementName Value="5" /> 
</SomeModel> 
+3

是的,這給了我需要的XML模式,但是它爲模型增加了不必要的間接和複雜程度。現在,而不僅僅是Object.SomeProperty,我有Object.SomeProperty.Value。我意識到,我可能無法使用內建的序列化兩種方式 - 但這是問題的本質。 – IUnknown

+2

這就是內置串行器的工作原理。 –

+0

我知道這有點舊,但是我會將隱式投射操作從'T'添加到'SomeInfo ',反之亦然。 – Shago

3

種類,使用XmlAttribute而不是XmlElement,但它不會看起來像你想要的。它看起來像下面這樣:

<SomeModel SomeStringElementName="testData"> 
</SomeModel> 

我能想到的只有這樣才能達到你想要的(本地)將有指向名爲SomeStringElementName和SomeInfoElementName對象的屬性,其中類包含一個名爲單個吸附劑「值」。您可以更進一步並使用DataContractSerializer,以便包裝類可以是私有的。 XmlSerializer不會讀取私有屬性。

// TODO: make the class generic so that an int or string can be used. 
[Serializable] 
public class SerializationClass 
{ 
    public SerializationClass(string value) 
    { 
     this.Value = value; 
    } 

    [XmlAttribute("value")] 
    public string Value { get; } 
} 


[Serializable]      
public class SomeModel      
{      
    [XmlIgnore]      
    public string SomeString { get; set; }      

    [XmlIgnore]      
    public int SomeInfo { get; set; } 

    [XmlElement] 
    public SerializationClass SomeStringElementName 
    { 
     get { return new SerializationClass(this.SomeString); } 
    }    
} 
+0

嗨克里斯,是的,我可以使用XmlAttribute,但正如你所說,它不會給我需要的結果。我希望能夠在不編寫自己的序列化代碼的情況下獲得我所需要的內容。 – IUnknown

+0

@IUnknown--我把一種可能的方式放在一起,實現你想要的。這不太好,創建類來獲得節點,所以如果別人知道更好的方法,我也會感興趣。 –