首页 文章

没有注释的WCF Contract [重复]

提问于
浏览
2

这个问题在这里已有答案:

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

4 回答

  • 5

    您可以使用 MetadataType 属性和元数据模型类,以便将注释与模型分开 .

    例如:

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

    如果不向类添加任何序列化属性,并将其用作WCF服务 Contract 方法的一部分,则WCF将使用默认序列化规则来生成数据协定 . 这意味着该类将隐含地成为 [DataContract]both getset 访问器将隐式变为 [DataMember] .

    您需要应用属性的唯一时间是您要覆盖默认行为,例如隐藏一些属性,应用名称空间等 . 只要默认行为符合您的需要,它就不是严格要求的 .


    回应您的后续行动:

    据我所知,没有完全外部的方法来改变给定类的 DataContractSerializer 的序列化行为;每个选项都要求序列化的类至少有一定程度的归属 . 正如@Yair Nevet在下面描述的那样,我将现有域对象转换为数据 Contract 的首选方法是 MetadataType 属性 .

    或者,您可以通过执行问题中的建议来绕过整个问题:不要序列化域对象,而是创建自定义DTO对象并将其序列化 . 每当我使用实体框架时,我倾向于这样做,因为序列化这些可能很棘手 . 如果您的域对象内置了大量行为,这也是一种很好的方法 - 您可以清楚地分离"data being passed around"与"objects participating in my business logic."

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

  • 1

    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; }
    }
    

    在前面的代码示例中,我明确设置了类和成员的名称 . 这将允许我重构名称而不破坏消费者代码 . 因此,如果某人决定我的 class 应该被命名为CustomerDetail而不是Customer,我仍然可以将该名称保留为Customer,以便我的服务的消费者继续工作 .

  • 2

    你总是可以使用DTO . 创建一个单独的类,其中包含序列化对象所需的所有内容 . 然后将您的域模型投影到DTO . 您可以使用AutoMapper之类的东西来简化此过程 .

    Regarding Performance

    除非每个类有数百个,可能是数千个,或者对象或者有大量属性,否则转换到DTO和从DTO转换的行为可能不是那么多的性能开销 .

    如果您使用的是EF,并且没有对每个属性进行序列化,您甚至可以通过将EF查询直接投影到DTO来减少一些开销 .

    这是一个戏剧性的案例,但我有(设计不佳)数据库模型,每种类型有50个属性 . 通过更改为只有我关心的10-15个属性的DTO,我几乎可以将WCF服务的性能提高一倍 .

相关问题