2015-11-21 40 views
0

我一直在閱讀很多關於c#xml序列化的其他問題,但似乎無法解決這個我有的小理解問題。C#XML序列化問題{get {...}}

我希望它不會太長,請考慮下面的代碼:

public class Grandparent { 
    [XmlAttribute(AttributeName = "name")] 
    public string Name { get; set; } 
} 



public class ParentA : Grandparent { 
    private Grandparent _neighbor; 

    [XmlAttribute(AttributeName = "neighbor")] 
    public string NeighborName { get { return _neighbor.Name; } } 

    public ParentA() : this(null) { } 
    public ParentA(Grandparent neighbor) { 
     setNeighbor(neighbor); 
    } 

    public void setNeighbor(Grandparent neighbor) { 
     // Do some checking 
     _neighbor = neighbor; 
    } 
} 



public class ParentB : Grandparent { 
    private List<Grandparent> _people; 

    [XmlElement(ElementName = "child1")] 
    public List<ChildA1> Children1 { get { return _people.Where(p => p.GetType() == typeof(ChildA1)).Cast<ChildA1>().ToList(); } } 

    [XmlElement(ElementName = "child2")] 
    public List<ChildA2> Children2 { get { return _people.Where(p => p.GetType() == typeof(ChildA2)).Cast<ChildA2>().ToList(); } } 

    [XmlElement(ElementName = "parentc")] 
    public List<ParentC> ParentsC { get { return _people.Where(p => p.GetType() == typeof(ParentC)).Cast<ParentC>().ToList(); } } 

    public ParentB() { 
     _people = new List<Grandparent>(); 
    } 

    public void AddPerson(Grandparent person) { 
     // Do some checking 
     _people.Add(person); 
    } 
} 



public class ParentC : Grandparent { 
} 



public class ChildA1 : ParentA { 
} 



public class ChildA2 : ParentA { 
} 



[XmlRoot("myroot")] 
public class Model { 
    private List<ParentB> _parents; 

    [XmlElement(ElementName = "parentb")] 
    public List<ParentB> Parents { get { return _parents; } } 

    public Model() { 
     _parents = new List<ParentB>(); 
    } 

    public void AddParent(ParentB parent) { 
     // Do some checking 
     _parents.Add(parent); 
    } 

    public string Serialize() { 
     XmlSerializer serializer = new XmlSerializer(typeof(Model)); 

     using (StringWriter writer = new StringWriter()) { 
      serializer.Serialize(writer, this); 
      return writer.ToString(); 
     } 
    } 
} 

現在讓我們創建一個模型,並用一些數據填充它:

Model model = new Model(); 

ChildA1 child1 = new ChildA1 { Name = "Alex" }; 
ChildA1 child2 = new ChildA1 { Name = "Ben" }; 
ChildA2 child3 = new ChildA2 { Name = "Jim" }; 
ChildA2 child4 = new ChildA2 { Name = "Pete" }; 

child1.setNeighbor(child2); 
child2.setNeighbor(child1); 
child3.setNeighbor(child4); 
child4.setNeighbor(child3); 

ParentB parent1 = new ParentB { Name = "Fred" }; 
ParentC parent2 = new ParentC { Name = "Sam" }; 

parent1.AddPerson(parent2); 
parent1.AddPerson(child1); 
parent1.AddPerson(child2); 
parent1.AddPerson(child3); 
parent1.AddPerson(child4); 

model.AddParent(parent1); 

textBox1.Text = model.Serialize(); 

這是輸出XML我們得到:

<?xml version="1.0" encoding="utf-16"?> 
<myroot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <parentb name="Fred"> 
    <child1 name="Alex" /> 
    <child1 name="Ben" /> 
    <child2 name="Jim" /> 
    <child2 name="Pete" /> 
    <parentc name="Sam" /> 
    </parentb> 
</myroot> 

現在我們終於來到了我的問題的原因: 從我的理解只有公共數據纔會被序列化,這意味着方法(或從它們返回的數據)不會被序列化。 因此,像public string Test { get; set; }這樣的東西可能會翻譯成公共領域......所以可能會被序列化。 但是這個怎麼樣:public string Test { get { return _someString; } }? 這只是一個像public string get_Test() { return _someString; }正常方法的語法糖不是嗎?我們知道從方法返回的數據沒有被序列化嗎?

是的,還有就是證明:

[XmlAttribute(AttributeName = "neighbor")] 
public string NeighborName { get { return _neighbor.Name; } } 

這不是正在連載。 但是等等..什麼?下一個作品:

[XmlElement(ElementName = "child1")] 
public List<ChildA1> Children1 { get { return _people.Where(p => p.GetType() == typeof(ChildA1)).Cast<ChildA1>().ToList(); } } 

我想我可以說,像public string Test { get { return _someObj.someString; } }一些簡單的getter只是訪問一個數據域和可能翻譯的東西,可以被序列化?但是上面發佈的更復雜的getter確實有效,爲什麼簡單版本(鄰居)不起作用? 我必須錯過一些東西......它主演着我的眼睛,但我看不到它。

請幫我解決這個謎題。

PS:上面的類和代碼僅僅是代碼的重建,實際上提出了這個問題。它的結構相似,生成的輸出也非常相似。我確實在應用程序中快速實現並測試了這段代碼,它似乎顯示了我的問題,請原諒我是否在克隆原始代碼的基本結構時發生了一些錯誤。

+0

是否打算用'XmlAttribute'和另一個用'XmlElement'裝飾? –

回答

1

只讀屬性未被序列化,因爲它們無法在往返中反序列化回對象數據。

但是,返回集合的只讀屬性的規則有一個例外 - >IEnumerable

反向串行程序在返回時執行的操作(當xml再次成爲類時)是將元素作爲類型添加到集合中。它從來不需要「設置」房產。

注:在你的情況下,如果你嘗試反序列化它會炸彈。但如果你改變它使用支持領域,它不會轟炸。

Introducing XML Serialization並注意第3段:

XML序列化不會轉換方法,索引器,私有字段, 或只讀屬性(除只讀的集合)。要序列化 所有對象的字段和屬性(公有和私有)都使用BinaryFormatter而不是XML序列化。

+0

謝謝,我錯過了。那麼在我的情況下,最佳做法是什麼?我總是希望鄰居屬性是鄰居的名字,所以我可以'私人祖父母_neighbor;私人字符串_neighborName;'並使setter:'公共字符串鄰居名稱{得到{返回_neighbor!= null? _neighbor.Name:_neighborName; } set {_neighborName = value; }}。我認爲這是一個不好的解決方案,因爲有人使用這個類可能會認爲他可以設置NeighborName屬性,但它只是有點被真實鄰居屬性的名稱遮蔽(並且我不想更改該對象的道具)。 – swent

+0

如果它總是被反序列化來創建它,你可以設置一個私有標誌來允許它被設置一次,並且在那之後拋出無效的操作異常 – toddmo