没有注释的WCF合同

本文关键字:WCF 合同 注释 | 更新日期: 2023-09-27 18:22:10

我想知道是否有任何方法可以在不使用[DataContract]和[DataMember]注释的情况下定义WCF Contract类。原因是我们目前拥有的域模型相当干净,所以我们希望保持这种方式。这里的最佳做法是什么?创建一个Transfer对象,并将域模型对象复制到一个传输对象中(该对象具有所需的注释,并且合同在客户端和服务器之间传输)?或者以某种方式不对对象模型进行注释,并以不同的方式指定合同。

没有注释的WCF合同

如果不将任何序列化属性添加到类中,并将其用作WCF服务约定方法的一部分,WCF将使用默认序列化规则生成数据约定。这意味着类将隐式成为[DataContract],而同时具有getset访问器的公共属性将隐式变成[DataMember]

需要应用属性的唯一时间是如果您想覆盖默认行为,例如隐藏某些属性、应用命名空间等。通常认为无论如何都这样做是一种好做法,因为依赖默认行为可能会在以后给您带来麻烦。(它还明确表示您的类是为WCF使用的)。但这并不是严格要求的,只要默认行为满足您的需求即可。


针对您的后续行动:

据我所知,对于给定的类,并没有完全外部的方法来更改DataContractSerializer的序列化行为;每个选项都至少需要对正在序列化的类进行某种级别的归因。正如@Yair Nevet在下面描述的那样,我将现有域对象转换为数据契约的首选方法是MetadataType属性。

或者,您可以按照问题中的建议绕过整个问题:不要序列化域对象,而是创建自定义DTO对象并序列化它们。例如,每当我使用实体框架时,我都倾向于这样做,因为序列化它们可能很棘手。如果你的域对象中有很多行为,这也是一个很好的方法——你可以清楚地区分"正在传递的数据"answers"参与我的业务逻辑的对象"

您经常会得到大量冗余代码,但它确实实现了对现有对象零更改的目标。

您可以使用MetadataType属性和元数据模型类来将注释与模型分离。

例如:

[MetadataType(typeof(MyModelMetadata))]
public class MyModel : MyModelBase {
  ... /* the current model code */
}
[DataContract]
public class MyModelMetadata {
    [DataMember] 
    public string Name { get; set; }
}

WCF能够在没有属性的情况下序列化对象。这些属性允许进行自定义。例如,这两个类将通过DataContractSerializer:进行相同的序列化

public class Customer
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}
[DataContract]
public class Customer
{
    [DataMember] public string FirstName { get; set; }
    [DataMember] public string LastName { get; set; }
}

值得一提的是,您确实应该用属性标记您的类。它们并不像你想象的那么"凌乱"。它实际上会让你在未来免于头痛。例如:

[DataContract(Name = "Customer")]
public class Customer
{
    [DataMember(Name = "FirstName")]
    public string FirstName { get; set; }
    [DataMember(Name = "LastName")]
    public string LastName { get; set; }
}

在上一个代码示例中,我显式地设置了类和成员的名称。这将允许我在不破坏消费者代码的情况下重构名称。因此,如果有人决定将我的类命名为CustomerDetail而不是Client,我仍然可以将名称保留为Customer以便我的服务的使用者继续工作。

您可以始终使用DTO。制作一个单独的类,该类包含序列化对象所需的所有内容。然后将您的域模型投影到DTO上。您可以使用类似AutoMapper的东西来简化这个过程。

关于性能

除非每个类有成百上千个对象或大量属性,否则转换到DTO和从DTO转换的行为可能不会带来太大的性能开销。

如果您使用的是类似EF的东西,并且您没有序列化每个属性,那么您甚至可以通过将EF查询直接投影到DTO上来减少一些开销。

这是一个引人注目的案例,但我有(设计糟糕的)数据库模型,每个类型有50多个属性。通过更改为只有我关心的10-15个属性的DTO,我几乎可以将WCF服务的性能提高一倍。