簡體   English   中英

DataContract 無法序列化集合成員

[英]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>

輸出已離開TestGroupDataMember 隨着我對洋蔥的深入了解,沒有包含更高的DataMember (即使來自抽象類)。 我曾嘗試將[KnownType(typeof(TestGroup))]TestGroupAbstractTestGroup但沒有成功。

問題:為什么我不能在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屬性修飾的interfaceclass ,其中服務包含返回上述抽象類型之一的方法? 如果是這樣,那么您還需要使用ServiceKnownTypesAttribute屬性裝飾返回抽象類型的所述interfaceclass方法。 一個快速而骯臟的例子如下:

[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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM