【问题标题】:Collection interfaces and WCF集合接口和 WCF
【发布时间】:2011-05-07 15:59:42
【问题描述】:

我正在使用 C# 和 WCF 来提供 Web 服务。我有一个实现 IEnumerable 的类的成员变量。我试图通过以下方式将其序列化为我的数据合同的一部分:

[DataContract]
class Item
{
    [DataMember]
    private IEnumerable<KeyValuePair<string, object>> Member1
    {
        get { return this._Properties; }
        set { this._Properties = Value; }
    }
}

_Properties 的类型是:

class PropertiesCollection:IEnumerable<KeyValuePair<string, object>>
{
    ...
}

我认为 WCF 会将 Member1 序列化为 IEnumerable,因为这是我给该成员的类型,但我收到了 InvalidDataContractExceptiom,并带有以下消息:

类型 PropertyCollection 无法序列化。考虑使用 DataContractAttribute 属性对其进行标记,并使用 DataMemberAttribute 属性标记您想要序列化的所有成员。如果类型是集合,请考虑使用 CollectionDataContractAttribute 对其进行标记。有关其他支持的类型,请参阅 Microsoft .NET Framework 文档。

似乎 WCF 正在查看通过 Member1 (PropertyCollection) 传递的对象的运行时类型,而不是属性的类型 (IEnumenable)。这种理解正确吗?将 [CollectionDataContract] 添加到 PropertiesCollection 的唯一解决方法是什么?如果可能的话,我更愿意保持服务合同是非特定的(即它只知道 iot 是一个 IEnumerable)。

【问题讨论】:

    标签: c# .net wcf


    【解决方案1】:

    突然想到:我认为您需要使用 KnownType 属性来装饰 Member1 属性。

    见:http://msdn.microsoft.com/en-us/library/ms730167.aspx

    [DataContract]
    [KnownType(typeof(PropertiesCollection))] //<--- this guy here
    class Item
    {
        [DataMember]
        private IEnumerable<KeyValuePair<string, object>> Member1
        {
            get { return this._Properties; }
            set { this._Properties = Value; }
        }
    }
    

    在上面的链接中添加来自 Example2 的代码,以显示即使属性是 Class 装饰器,它也适用于 DataMember:

    public interface ICustomerInfo {}
    
    [DataContract(Name = "Customer")]
    public class CustomerTypeA : ICustomerInfo {}
    
    [DataContract(Name = "Customer")]
    public class CustomerTypeB : ICustomerInfo {}
    
    [DataContract]
    [KnownType(typeof(CustomerTypeB))] //<-- check it! This applies to 'buyer'
    public class PurchaseOrder
    {
        [DataMember]
        ICustomerInfo buyer;
    
        [DataMember]
        int amount;
    }
    

    【讨论】:

    • 假设它有效,为什么如果我想在将来将我的 PropertiesCollection 切换到 List>。这不会破坏 DataContract 吗?我想依赖 IEnumerable 而不是我当前的具体实现,即 PropertiesCollection。
    • Knowntype 用于表示“我是说我会给你一只动物,但如果我给你一只狗或猫,请不要惊慌。它们是动物类型,所以这很酷”。因此,只要您选择返回的类型实现了 Ienumerable>,并且您说它是已知类型,那么一切都应该是好的。
    • 你的答案看起来很可疑。 [KnownType] 应该应用于 DataContract 而不是 DataMember!
    • 查看我发布的链接中的 Example2。您是对的,因为您在 DataContract 上设置了属性,但它将应用于成员。您必须将 DataContract 属性放在 PropertiesCollection 上才能正常工作。
    【解决方案2】:

    DataContract 必须在 PropertiesCollection 类定义前面:

     [DataContract]
     class PropertiesCollection:IEnumerable<KeyValuePair<string, object>>
     {
        ...
     }
    

    每个进入序列化的类型都应该是[DataContract]或者[Serializable]

    【讨论】:

    • 不是这样的。集合的序列化是自动的,不需要 [DataContract]。
    • 那些属于 PropertiesCollection 成员的“对象”呢?可以序列化吗?那些成员到底是什么?
    • 假设它们要么是内置类型,要么是 DataContract 的 KnownTypes。如果不是,我们会在反序列化时遇到异常,这是意料之中的。
    【解决方案3】:

    对这个问题的真正回答是,类型必须满足一些要求才能成为有效的集合 DataContract:

    1. 它必须有一个无参数的构造函数
    2. 它必须有一个添加方法。

    当我实现这些时,我的问题就消失了。

    【讨论】:

      【解决方案4】:

      最简单的解决方案:

      1. 创建包含键和值的新可序列化类
      2. 在任何集合中传递此类

      【讨论】:

        猜你喜欢
        • 2013-12-20
        • 1970-01-01
        • 1970-01-01
        • 2011-02-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-13
        • 2013-04-08
        相关资源
        最近更新 更多