【问题标题】:Web API 2 XML Serialization and DataContractsWeb API 2 XML 序列化和 DataContracts
【发布时间】:2016-12-09 18:33:41
【问题描述】:

当我的 Web API 2 解决方案在请求 XML 时尝试解析结果时,我遇到了错误。

通过更多的研究来找出答案。使用默认 XML 序列化程序解析字典时会出现问题。

基类中的属性如下所示:

public Dictionary<string, CustomObject> MyThings{ get; set; }

这可以在没有所有 DataContract 和 DataSerialization 属性的情况下工作。

但是,如果我做同样的事情但将值类型定义为“对象”,我会收到错误:

如果您正在使用 DataContractSerializer 或将任何静态未知的类型添加到已知类型列表中,请考虑使用 DataContractResolver - 例如,通过使用 KnownTypeAttribute 属性或将它们添加到传递给序列化程序的已知类型列表中。

这很好,据我了解,我需要用预期的类型装饰类,并且序列化程序理论上应该将对象序列化为 XML。

当我装饰类时得到同样的错误。

我不知道这是否是因为在解析“对象”类型方面仍然存在限制。但是从我在其他人的问题和示例中看到的情况来看,如果说该属性是类型的,则它可以工作;

object 

而不是

IDictionary<string, object>

我只是想知道我是否误解了如何使用 DataContract、KnownType 和/或 DataMember 属性,或者这实际上是否仍然是使用默认 XML 序列化程序解析字典的限制。

我在这里查看了许多示例和问题,但没有找到一个好的解决方案。

过去有没有人提出过这个问题?如果是这样,您是如何绕过限制的?

我尝试过使用 KeyValuePairs 列表,但也失败了。

谢谢!

例子:

    [DataContract]
    [KnownType(typeof(Dictionary<string, Type_X>))]
    [KnownType(typeof(Dictionary<string, Type_Y>))]
    public abstract class BaseClass
    {
        [DataMember]
        public Dictionary<string, object> BaseDictionary{ get; set; }

        public BaseClass()
        {
            BaseDictionary = new Dictionary<string, object>();
        }
    }

【问题讨论】:

    标签: c# xml serialization asp.net-web-api2 datacontractserializer


    【解决方案1】:

    您需要将Type_XType_Y 声明为已知类型:

    [DataContract]
    [KnownType(typeof(Type_X))]
    [KnownType(typeof(Type_Y))]
    public abstract class BaseClass
    {
        [DataMember]
        public Dictionary<string, object> BaseDictionary { get; set; }
    
        public BaseClass()
        {
            BaseDictionary = new Dictionary<string, object>();
        }
    }
    

    您所做的是将Dictionary&lt;string, Type_X&gt; 声明为已知类型,但是在对象图中未遇到该类型。相反,您需要声明将显示为字典 的实际类型,因为这些类型无法静态推断。

    完成后,数据协定序列化程序将生成类似于以下内容的 XML:

    <ConcreteClass xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Question41066771">
        <BaseDictionary xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
            <d2p1:KeyValueOfstringanyType>
                <d2p1:Key>X</d2p1:Key>
                <d2p1:Value i:type="Type_X">
                    <X>x</X>
                </d2p1:Value>
            </d2p1:KeyValueOfstringanyType>
            <d2p1:KeyValueOfstringanyType>
                <d2p1:Key>Y</d2p1:Key>
                <d2p1:Value i:type="Type_Y">
                    <Y>y</Y>
                </d2p1:Value>
            </d2p1:KeyValueOfstringanyType>
        </BaseDictionary>
    </ConcreteClass>
    

    给定具体的类:

    [DataContract]
    public class ConcreteClass : BaseClass
    {
    }
    
    [DataContract]
    public class Type_X
    {
        [DataMember]
        public string X { get; set; }
    }
    
    [DataContract]
    public class Type_Y
    {
        [DataMember]
        public string Y { get; set; }
    }
    

    i:type 属性是一个w3c standard attribute,它允许元素声明其类型。数据合约序列化程序使用它来指示被序列化的多态类型的实际合约名称。更多信息,请参阅Data Contract Known Types

    【讨论】:

    • 啊...是的,我知道它在做什么。我没有单击这是用于继承链,以便序列化程序知道要尝试和序列化的类型。我的解决方案非常相似,感谢您为我指明了正确的方向!
    猜你喜欢
    • 2016-06-22
    • 2013-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-25
    • 2012-08-29
    • 2016-12-11
    • 1970-01-01
    相关资源
    最近更新 更多