WCF 中的 DataContract 有啥意义?

Posted

技术标签:

【中文标题】WCF 中的 DataContract 有啥意义?【英文标题】:What's the point of a DataContract in WCF?WCF 中的 DataContract 有什么意义? 【发布时间】:2010-09-23 02:42:54 【问题描述】:

VS.net 在您创建 WCF 项目时创建一个模板。

它将一个类添加到 iService1.cs 文件中:

// Use a data contract as illustrated in the sample below to
// add composite types to service operations.
[DataContract]
public class CompositeType

    bool boolValue = true;
    string stringValue = "Hello ";

    [DataMember]
    public bool BoolValue
    
        get  return boolValue; 
        set  boolValue = value; 
    

    [DataMember]
    public string StringValue
    
        get  return stringValue; 
        set  stringValue = value; 
    

既然 WCF 服务可以返回任何用户定义的类,为什么要使用 DataContract 和 CompositeType 类?

我可以返回类似的东西:

 [OperationContract]
MyUserCollection GetUsers();

我错过了什么?

【问题讨论】:

如果您在电线的两端都有 .NET,那很好。如果您有一个 Java 客户端调用您的服务怎么办?如果将数据放在 DataContracts 中,则该信息将存储在 WSDL/XSD 元数据中,并且也可以由 .NET 以外的客户端使用。 我发现 marc_s 的评论是最有用和最直接的,但在阅读其他答案时,我发现 WolveFred 的评论让我感到困惑。所以请你澄清一下。赞成,因为它仍然是最直接的答案。 【参考方案1】:

DataContract 只是对服务边界两边都可以理解的类型的正式定义。

如果您返回(如您的示例中所示)“MyUserCollection”对象,则您的服务的消费者将需要引用您的服务/系统的内部结构,这违反了 SOA 明确边界的原则。通过使用 DataContract,您可以以松散耦合的方式发布返回类型的结构。

【讨论】:

我的 WCF 正在被我编写的应用程序所消耗,所以在所有实际用途中它应该没问题(破坏 SOA)。你同意吗? 您可能可以,但您为什么要这样做?添加属性很容易,并且是使用 WCF 的推荐方法。 Scott,所以我只需将 MyUserCollection 添加到 CompositeType 类和宾果游戏!? 您可能需要将 [KnownType(MyUserCollection)] 属性添加到 CompositeType 类。如果没有,我会先尝试;如果它不起作用,你会得到一个异常,说将 MyUserCollection 添加到已知类型列表中,在这种情况下,只需添加属性。 如果服务提供 JSON 就不需要它了?【参考方案2】:

要注意的另一件有趣的事情是,如果您使用 DataContract 装饰您的代码,您可以对客户端可以看到的内容以及必须发送回您的服务的内容进行大量控制。例如:

[DataContract]
public class SampleClass

    [DataMember(IsRequired=true)]
    public int MyRequiredProperty  get; set; 

    [DataMember]
    public int MyOptionalProperty  get; set; 

    public int MyInternalProperty  get; set; 

在上面的示例中,您定义了在接收数据时,您必须拥有 MyRequiredProperty,并且您可以拥有或不拥有 MyOptionalProperty。此外,客户端永远不会看到 MyInternalProperty(例如,这可能是一些有助于您的内部逻辑的属性,但您不希望它在客户端级别公开)。

【讨论】:

【参考方案3】:

还有一个重要的用途,你可以改变类和属性的名称。这是序列化和反序列化过程中的一个方便的功能。

[DataContract(Name="EmployeeName")]
public class Person

   [DataMember(Name="FullName")]
   public string Name  get; set; 

   [DataMember(Name="HomeAddress")]
   public string Address  get; set; 

【讨论】:

【参考方案4】:

回答“marc_s”:

"如果您的两端都有 .NET 电线,那很好。如果你 有一个 Java 客户端调用您的 服务?如果你把你的数据放在里面 DataContracts,该信息获取 存储在 WSDL/XSD 元数据和 可以被其他客户使用 .NET 也是如此。”

我认为这是错误的。让我们尝试这样做:

    使用 WCF 的默认示例 项目与类 类上的 DataContract 属性 和成员上的 DataMember,以及 返回此类型的方法。 构建它并显示 wsdl。 xsd 包含 CompositeType 定义。好的。 现在让我们删除所有属性 DataContract 和 DataMember 构建它并显示 wsdl。 xsd 仍然包含 ComposityType 定义! (使用 SCM 软件更明显,它显示第 2 步和第 4 步之间的文件没有差异)

因此,Java 客户端应该在没有 DataContract 和 DataMember 的情况下管理它!是我错了还是怎么了?

【讨论】:

你没有看错,沃尔特。 (我开玩笑,我开玩笑)交易是您的消费者仍然需要知道格式,对吗?如果您在两边都在 .NET-land 中,那么只需引用该对象就可以了。您不能 [容易] 将 .NET 对象导入 Java,因此您必须以另一种方式公开该格式。不知道为什么 4 会是真的——我相信交易是不应该的,对吗?虽然我承认我来这里主要是为了有机会引用 El Duderino。【参考方案5】:

我不同意发帖者所说的“DataContract 只是一种类型的正式定义,可以在服务边界的两侧理解。”

这里的关键字是“类型”。在 .NET 中,类型是可以具有字段、属性和方法的对象。但是,当您在 WCF 服务中使用DataContract 装饰一个类时,结果并不是该类被神奇地移植到调用代码中;而是不是由一个长镜头!在调用代码中,您将有一个“代理”类。代理类接收表示数据协定内容的 XML。调用代码可以通过代理类接收这些 XML 值,但它确实让调用代码访问用datacontract 装饰的类的内部。

【讨论】:

您的“类型是对象”的说法令人困惑和误导。 Object 是一种类型,因为 Integers 和 Strings 是类型。为清楚起见,type 是一个标识符,其中 Object 是一个,String 是另一个,Integer、Boolean 等也是。【参考方案6】:

也许不常用,我们可以使用 [DataContract] 来传递私有变量。如果不使用 [DataContract] 属性,DataContractSerializer 将仅对公开可见的类型进行序列化/反序列化。

[DataContract]
public class SampleClass
    
    [DataMember]
    private int MyPrivateProperty  get; set; 

(注意:如果您正在生成代理,则私有成员将公开为公共)

【讨论】:

以上是关于WCF 中的 DataContract 有啥意义?的主要内容,如果未能解决你的问题,请参考以下文章

WCF:MessageContract、DataContract ... 感到困惑?

在 WCF 中命名通用 DataContract

WCF -Rest- DataContract:反序列化 XML 包装的响应

WCF DataContract 与普通类 [重复]

WCF 数据契约(DataContract)

c# WCF 与 POCO DataContract