2009-01-23 61 views

回答

12

A工作液被貼在我的博客:

http://borismod.blogspot.com/2009/04/wcf-collectiondatacontract-and.html

UPD:謝謝,您的評論,傑夫。 這裏是一個非泛型類的總結。一個完整的通用的解決方案可以在我的博客新文章中找到: http://borismod.blogspot.com/2009/06/v2-wcf-collectiondatacontract-and.html


[DataContract(IsReference = true)]  
public class EntityCollectionWorkaround : ICollection 
    { 

     #region Constructor 
     public EntityCollectionWorkaround() 
     { 
      Entities = new List(); 
     } 
     #endregion 

     [DataMember] 
     public int AdditionalProperty { get; set; } 

     [DataMember] 
     public List Entities { get; set; } 

     #region ICollection Members 
      // Implement here members of ICollection by wrapping Entities methods 
     #endregion 

     #region IEnumerable Members 
      // Implement here members of IIEnumerable by wrapping Entities methods 
     #endregion 

    } 
 
+2

好博客文章,但如果你在這裏給出了一個快速總結,這將是很好的。 – 2009-04-21 20:59:07

3

您可能需要考慮爲您的課程實施自定義序列化。執行IXmlSerializable可能最容易,輸出您的定製屬性的值,然後使用DataContractSerializer將集合中子項的實例序列化爲輸出。

+0

對於我來說,`IXmlSerializable`可以工作,但集合內部的結構很大,一旦我在集合中實現了`ReadXml`和`WriteXml`,我就不得不手動將層次結構...在這一點上,我不妨自定義滾動整個事情。我在下面添加了一個答案,描述瞭如何通過使用集合上的常規「DataContract」屬性來繞過「IXmlSerializable」。 – jwatts1980 2015-03-12 15:01:12

1

這個答案的目的是作爲一個附加到@BorisModylevsky給出了答案。我可以找到這個問題的每個解決方案都建議使用IXmlSerializable。但這裏是我的問題:我有一個分層母子結構是這樣

public class Project 
{ 
    //Several properties here... 

    public ItemCollection Items { get; private set; } 

    public Project() 
    { 
     Items = new ItemCollection(); 
    } 
} 

public class ItemCollection : IList<ItemDetails> 
{ 
    private List<ItemDetails> _list = new List<ItemDetails>(); 

    public Project Parent { get; private set; } 

    ///dependency injection... 
    public ItemCollection(Project parent) 
    { 
     this.Parent = parent; 
    } 

    //Interface methods here working with _list... 
    //In the `Add(ItemDetails item)` method, I update incoming items with item.Parent = this.Parent. 
} 

public class ItemDetails 
{ 
    public Project Parent { get; set; } 

    //Several properties here, including some sub classes 

    ///dependency injection... 
    public ItemDetails(Project parent) 
    { 
     this.Parent = parent; 
    } 
} 

爲了使這項工作DataContractSerializer我不得不添加一些私人的構造,以及所需要的屬性:

[DataContract(IsReference=true)] 
public class Project 
{ 
    [DataMember(Order=0)] 
    public ItemCollection Items { get; private set; } 

    //[DataMember(Order=##)] 
    //Several properties here, including some other sub classes 

    public Project() 
    { 
     Items = new ItemCollection(); 
    } 
} 

[CollectionDataContract(IsReference=true)] 
public class ItemCollection : IList<ItemDetails> 
{ 
    private List<ItemDetails> _list = new List<ItemDetails>(); 

    [DataMember(Order=0)] 
    public Project Parent { get; private set; } 

    ///dependency injection... 
    public ItemCollection(Project parent) 
    { 
     this.Parent = parent; 
    } 

    //Private constructor for use with DataContractSerializer 
    private ItemCollection() { } 

    //Interface methods here working with _list... 
} 

[DataContract(IsReference=true)] 
public class ItemDetails 
{ 
    [DataMember(Order=0)] 
    public Project Parent { get; private set; } 

    //[DataMember(Order=##)] 
    //Several properties here, including some sub classes 

    ///dependency injection... 
    public ItemDetails(Project parent) 
    { 
     this.Parent = parent; 
    } 

    //Private constructor for use with DataContractSerializer 
    private ItemDetails() { } 
} 

的問題是,XML創建的集合是這樣的:

<Project> 
    <!--OTHER PROJECT PROPERTIES HERE--> 
    <Items z:Id="i11"> 
     <ItemDetails z:Id="i12"> 
      <Parent z:Ref="i1"/> 
      <!--OTHER PROPERTIES HERE--> 
     </ItemDetails> 
     <ItemDetails z:Id="i16"> 
      <Parent z:Ref="i1"/> 
      <!--OTHER PROPERTIES HERE--> 
     </ItemDetails> 
    </Items> 
</Project> 

Items下沒有Parent財產在XML中。最好我可以告訴,CollectionDataContract不支持集合類中的任何其他屬性。在這種情況下,如果我實現了IXmlSerializable就像很多人所建議的那樣,那麼我將被手動卡住序列化和反序列化ItemDetails中的大量結構(爲簡潔起見我沒有在這裏顯示)。在這種情況下,DataContractSerializer對我來說幾乎毫無價值。

但隨着@BorisModylevsky回答上面,我改變了代碼到這個:

[DataContract(IsReference=true)] 
public class Project 
{ 
    [DataMember(Order=0)] 
    public ItemCollection Items { get; private set; } 

    //[DataMember(Order=##)] 
    //Several properties here, including some other sub classes 

    public Project() 
    { 
     Items = new ItemCollection(); 
    } 
} 

[DataContract(IsReference=true)] 
public class ItemCollection : IList<ItemDetails> 
{ 
    //Refactored _list to ItemsList. I didn't have to; I could have used [DataMember(Name="ItemsList", Order=1)] 
    [DataMember(Order=1)] 
    private List<ItemDetails> ItemsList = new List<ItemDetails>(); 

    [DataMember(Order=0)] 
    public Project Parent { get; private set; } 

    ///dependency injection... 
    public ItemCollection(Project parent) 
    { 
     this.Parent = parent; 
    } 

    //Private constructor for use with DataContractSerializer 
    private ItemCollection() { } 

    //Interface methods here working with ItemsList... 
} 

[DataContract(IsReference=true)] 
public class ItemDetails 
{ 
    [DataMember(Order=0)] 
    public Project Parent { get; private set; } 

    //[DataMember(Order=##)] 
    //Several properties here, including some sub classes 

    ///dependency injection... 
    public ItemDetails(Project parent) 
    { 
     this.Parent = parent; 
    } 

    //Private constructor for use with DataContractSerializer 
    private ItemDetails() { } 
} 

總結:我改變CollectionDataContractDataContract並添加DataMember到我現在用的集合中的私人列表。這是可行的,因爲DataContractSerializer可以獲取和設置私有屬性/字段。現在XML看起來像這樣:

<Project> 
    <!--OTHER PROJECT PROPERTIES HERE--> 
    <Items z:Id="i11"> 
     <Parent z:Ref="i1"/> 
     <ItemsList> 
      <ItemDetails z:Id="i12"> 
       <Parent z:Ref="i1"/> 
       <!--OTHER PROPERTIES HERE--> 
      </ItemDetails> 
      <ItemDetails z:Id="i16"> 
       <Parent z:Ref="i1"/> 
       <!--OTHER PROPERTIES HERE--> 
      </ItemDetails> 
     </ItemsList> 
    </Items> 
</Project> 

這是我的目的,完美的作品。它根據需要序列化和反序列化。

相關問題