![](/img/trans.png)
[英]Why would a WCF DataContract not serialize members in alphabetical order?
[英]DataContract not able to serialize collection members
我的數據最好被描述為“洋蔥狀”,因為每個外層都建立在它下面的一層之上。 下面你會看到一個大大簡化的版本(我的版本更深了幾層,但在每個級別都表現出相同的行為)。
[CollectionDataContract]
public abstract class AbstractTestGroup : ObservableCollection<AbstractTest>
{
[DataMember]
public abstract string Name { get; set; }
}
[CollectionDataContract]
[KnownType(typeof(Test))]
public class TestGroup : AbstractTestGroup
{
public override string Name
{
get { return "TestGroupName"; }
set { }
}
[DataMember]
public string Why { get { return "Why"; } set { } }
}
[DataContract]
public abstract class AbstractTest
{
[DataMember]
public abstract string SayHello { get; set; }
}
[DataContract]
public class Test : AbstractTest
{
//Concrete class - members in this class get serialized
[DataMember]
public string Month { get { return "June"; } set { } }
public override string SayHello { get { return "HELLO"; } set { } }
}
我創建了一個TestGroup
實例,並使用ObservableCollection
附帶的.Add
向其中添加了Test
對象。
當我序列化和反序列化這個結構時,我得到以下信息
<TestGroup xmlns="http://schemas.datacontract.org/2004/07/WpfApplication2" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<AbstractTest i:type="Test">
<SayHello>HELLO</SayHello>
<Month>June</Month>
</AbstractTest>
</TestGroup>
輸出已離開TestGroup
的DataMember
。 隨着我對洋蔥的深入了解,沒有包含更高的DataMember
(即使來自抽象類)。 我曾嘗試將[KnownType(typeof(TestGroup))]
到TestGroup
和AbstractTestGroup
但沒有成功。
問題:為什么我不能在TestGroup
類中序列化DataMember
Why
?
后續問題:是否有其他方法來序列化和反序列化這種形狀的結構? 我計划在本地使用輸出來“加載”用戶指定的配置。 如果可以避免的話,我寧願不必指定我自己的序列化方案。
對於那些感興趣的人來說,我是如何生成類、序列化和反序列化它的。
TestGroup tg = new TestGroup();
tg.Add(new Test());
DataContractSerializer ser = new DataContractSerializer(typeof(TestGroup));
MemoryStream memoryStream = new MemoryStream();
ser.WriteObject(memoryStream, tg);
memoryStream.Seek(0, SeekOrigin.Begin);
string str;
using (StreamReader sr = new StreamReader(memoryStream))
str = sr.ReadToEnd();
編輯:對於值得的,我嘗試改為使用Serializable
並遇到相同的問題。
屬性Why沒有序列化的原因是因為TestGroup是一個集合。 而 DataContract 則特別對待集合。 最終結果是只存儲集合中的數據,不存儲任何屬性。
列表以任何其他列表都可以讀取它們的方式存儲。唯一的區別在於集合和字典之間。 一個很好的參考是http://msdn.microsoft.com/en-us/library/aa347850%28v=vs.110%29.aspx
更新:我在網上看到了一些可能對你有幫助的東西。 特別是,將抽象類屬性聲明更改為以下內容:
[DataContract]
[KnownTypes(typeof(Test))]
public abstract class AbstractTest { /* ... */ }
您可以查看 MSDN 上關於KnownTypesAttribute
的文檔。 顯然,還有一個構造函數重載,它接受一個字符串,該字符串解析為通過反射找到的方法名稱,並由DataContractSerializer
調用以確定基類的已知類型(如果您有多個已知類型和/或可能需要動態返回在編譯時可能未知的已知類型)。 還有用於設置已知類型的web.config
XML 配置。
更新:我注意到KnownTypesAttribute
屬性似乎在OP 的代碼示例中被濫用。 所以,我想用應該工作的完整代碼來詳細說明上面的內容。
[CollectionDataContract]
[KnownTypes(typeof(TestGroup))] // Need to tell DCS that this class's metadata will be included with members from this abstract base class.
public abstract class AbstractTestGroup : ObservableCollection<AbstractTest>
{
[DataMember]
public abstract string Name { get; set; }
}
[CollectionDataContract]
//[KnownTypes(typeof(Test))] -- You don't need this here....
public class TestGroup : AbstractTestGroup
{
[DataMember] // Even though this is a derived class, you still need to tell DCS to serialize this overridden property when serializing this type
public override string Name
{
get { return "TestGroupName"; }
set { }
}
[DataMember]
public string Why { get { return "Why"; } set { } }
}
[DataContract]
[KnownTypes(typeof(Test))] // Again, you need to inform DCS
public abstract class AbstractTest
{
[DataMember]
public abstract string SayHello { get; set; }
}
[DataContract]
public class Test : AbstractTest
{
//Concrete class - members in this class get serialized
[DataMember]
public string Month { get { return "June"; } set { } }
[DataMember] // Even though this is a derived class, you still need to tell DCS to serialize this overridden property when serializing this type
public override string SayHello { get { return "HELLO"; } set { } }
}
請參閱上面示例中KnownTypesAttribute
屬性旁邊的注釋。
更新:將DataMemberAttribute
特性添加到派生類的重寫屬性。
更新:好的,可能有一個額外的維度導致您引用的行為。 您是否有使用ServiceContractAttribute
屬性修飾的interface
或class
,其中服務包含返回上述抽象類型之一的方法? 如果是這樣,那么您還需要使用ServiceKnownTypesAttribute
屬性裝飾返回抽象類型的所述interface
或class
方法。 一個快速而骯臟的例子如下:
[ServiceContract]
//[ServiceKnownTypes(typeof(TestGroup))] -- You could also place the attribute here...not sure what the difference is, though.
public interface ITestGroupService
{
[OperationContract]
[ServiceKnownTypes(typeof(TestGroup))]
AbstractTestGroup GetTestGroup();
}
哈。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.