我有一個集合類,我用CollectionDataContract裝飾過。集合類還有一個我希望傳遞給服務客戶端的類。我曾嘗試將[DataMember]添加到該屬性,但在更新時未將其添加到客戶端中的類中。我可以將DataMember添加到WCF中的CollectionDataContract中嗎?
任何WCF專家都可以提供幫助嗎?
我有一個集合類,我用CollectionDataContract裝飾過。集合類還有一個我希望傳遞給服務客戶端的類。我曾嘗試將[DataMember]添加到該屬性,但在更新時未將其添加到客戶端中的類中。我可以將DataMember添加到WCF中的CollectionDataContract中嗎?
任何WCF專家都可以提供幫助嗎?
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
}
您可能需要考慮爲您的課程實施自定義序列化。執行IXmlSerializable
可能最容易,輸出您的定製屬性的值,然後使用DataContractSerializer
將集合中子項的實例序列化爲輸出。
對於我來說,`IXmlSerializable`可以工作,但集合內部的結構很大,一旦我在集合中實現了`ReadXml`和`WriteXml`,我就不得不手動將層次結構...在這一點上,我不妨自定義滾動整個事情。我在下面添加了一個答案,描述瞭如何通過使用集合上的常規「DataContract」屬性來繞過「IXmlSerializable」。 – jwatts1980 2015-03-12 15:01:12
這個答案的目的是作爲一個附加到@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() { }
}
總結:我改變CollectionDataContract
到DataContract
並添加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>
這是我的目的,完美的作品。它根據需要序列化和反序列化。
好博客文章,但如果你在這裏給出了一個快速總結,這將是很好的。 – 2009-04-21 20:59:07