【问题标题】:What is the standardized way to pass complex types in WCF?在 WCF 中传递复杂类型的标准化方法是什么?
【发布时间】:2010-10-23 07:38:41
【问题描述】:

我是WCF的新手,目前我正在开发一个TCP WCF服务,我不确定我是否正确理解传递参数,所以我建议你发表评论并给出一个标准化的方式。

为了搞清楚,我开发了一个用于测试目的的小型服务,它具有单一方法并依赖于公开单个类的外部 .Net dll。 服务合约代码

    [ServiceContract]
    public  interface IMyService
    {
        [OperationContract]
        int Test1(actionType at, calculationType ct, action a);
        [OperationContract]
        int Test2(DataSeries s);
    }

actionType,calculationType,action 是在外部 dll 中声明的枚举 DataSeries 是在 dll 中声明的类。

dll 中DataSeries 类的原始定义仅由[Serializable] 标记,其成员上没有[DataMember]

我在客户端和服务器端使用第三个 dll,令我惊讶的是两个应用程序都可以正常工作,而无需将 [DataContract] 放在 DataSeries 类上,也没有在枚举中使用任何 [EnumMember][DataMember] 在类内。

那到底是怎么回事?

另一个实验:

从客户端删除第 3 方并按原样使用服务 我发现 vs2008 生成枚举和DataSeries 类并用适当的属性标记它们? 喜欢

    [System.CodeDom.Compiler.GeneratedCodeAttribute      ("System.Runtime.Serialization", "3.0.0.0")]
    [System.Runtime.Serialization.DataContractAttribute(Name="actionType",  Namespace="http://schemas.datacontract.org/2004/07/DBInterface")]
    public enum actionType : int {

        [System.Runtime.Serialization.EnumMemberAttribute()]
        All = 0,

        [System.Runtime.Serialization.EnumMemberAttribute()]
        Buy = 1,

        [System.Runtime.Serialization.EnumMemberAttribute()]
        Sell = 2,
    }

【问题讨论】:

    标签: c# wcf argument-passing


    【解决方案1】:

    DataContractDataMemberEnumMember 属性由 DataContractSerializer(通常为 basicHttpBindingwsHttpBinding)使用。如果您使用 TCP 绑定 (netTcpBinding) 公开端点,则仅需要 SerializableAttribute。请注意,使用 DataContractSerializer 您只能将 SerializableAttribute 添加到您的类中,它会自动序列化所有字段。

    我会向您推荐以下内容:如果您希望您的服务可互操作,请使用 basicHttpBinding 并使用 DataContract 和 DataMember 属性标记您的类。如果您的客户端是 .NET 应用程序,请使用 netTcpBinding 并使用 SerializableAttribute 标记您的类。

    您还可以阅读此post 以比较不同的绑定。

    【讨论】:

    • 这是一个很好的答案,你能推荐链接/网站或书籍,让我了解有关 WCF 或 MSDN 的详细信息就足够了吗?
    【解决方案2】:

    但不使用 DataContract 或任何 属性,我找到了客户端 正常工作

    是的,这是真的 - 如果您使用的数据类型没有用 [DataContract] 标记,WCF 将尝试在它们上使用默认的 SOAP 序列化程序,并且只序列化所有公共的(所有公共属性)。

    它可以工作 - 但它可能不是你想要/期望的 - 所以我会同意 darin 的意见 - 总是在你的类型上使用明确的 [DataContract] 属性。您对自己(或其他需要稍后维护您的代码的程序员)的意图越清晰越好。这些在幕后发生的“魔术”有时会引起混乱 - 你最好不要过分依赖它们

    马克

    【讨论】:

      【解决方案3】:

      所以对我来说,我使用 [DataContract],并传入一个参数,然后返回一个数据合约。

      这提供了更大的灵活性,因为我可以使用新的可选属性来扩展数据合约,而不会破坏任何现有的客户端。

      我还为其创建数据联系人的枚举;因为我可以做同样的事情,扩展枚举而不破坏任何东西,我可以控制命名空间。

      [DataContract(Namespace = "http://namespace.mydomain.com/2009/05", Name = "ReferenceTypeData")]
      public enum GenderEnum
      {
          [EnumMember()]
          Unknown = 0,
          [EnumMember()]
          Male = 1,
          [EnumMember()]
          Female = 2
      }
      

      然后您必须在服务合同上注明

      [ServiceKnownType(typeof(GenderEnum))]
      public interface IServiceContract
      {
          ....
      }
      

      【讨论】:

      • 但没有使用 DataContract 或任何属性,我发现客户端工作正常
      猜你喜欢
      • 1970-01-01
      • 2012-12-08
      • 2022-08-15
      • 1970-01-01
      • 1970-01-01
      • 2014-03-13
      • 1970-01-01
      • 1970-01-01
      • 2021-11-21
      相关资源
      最近更新 更多