• WCF技术内幕 第9章(1)


    第9章 契约

    9.1 契约的定义

    WCF契约是标注了特定属性的.net类型,而且这些被标注的类型定义可以用来产生符合行业标准的WSDL和XSD文档。WCF契约会把这些类型映射为服务、操作、消息和消息中的部分。WCF有5种类型的契约:服务契约、操作契约、数据契约、消息契约和错误契约。

    9.2 WCF契约剖析

    服务契约

    using System;
    using System.ServiceModel;
    
    namespace ConsoleApplication20
    {
        [ServiceContract]
        interface IAndersService
        {
            [OperationContract]
            Int32? RequestReservation(DateTime? resDateTime);
            [OperationContract(IsOneWay = true)]
            void CancelReservation(Int32? reservationId);
        }
    }
    
        [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, Inherited = false, AllowMultiple = false)]
        public sealed class ServiceContractAttribute : Attribute
        {
            [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
            public ServiceContractAttribute();
    
            public Type CallbackContract { get; set; } //定义双工契约时使用
            public string ConfigurationName { get; set; } //配置文件中引用服务的简称
            public bool HasProtectionLevel { get; }
            public string Name { get; set; } //服务的名称
            public string Namespace { get; set; } //服务的命名空间
            public ProtectionLevel ProtectionLevel { get; set; } //当使用一个服务契约时,绑定必须达到的信息安全级别
            public SessionMode SessionMode { get; set; } //表示程序里使用的通道有必要,能够或不需要使用会话通道形状。它的枚举值是Allowed,Required和NotAllowed
        }


    操作契约

        [AttributeUsage(AttributeTargets.Method)]
        public sealed class OperationContractAttribute : Attribute
        {
            public OperationContractAttribute();
    
            public string Action { get; set; }
            public bool AsyncPattern { get; set; } //表示操作时否是异步编程模型的一部分
            public bool HasProtectionLevel { get; }
            public bool IsInitiating { get; set; }
            public bool IsOneWay { get; set; } //默认的情况下,所有的操作都是用请求/应答消息交换模式。如果想要使用数据表消息交换模式,则在这个方法上再设置IsOneWay属性为true
            public bool IsTerminating { get; set; }
            public string Name { get; set; }
            public ProtectionLevel ProtectionLevel { get; set; }
            public string ReplyAction { get; set; } //该属性可以把WS-Addressing的action与应答消息关联起来
        }

    数据契约

    数据契约会把.net类型映射到消息体上,而且它是消息序列化和反序列化的关键部分。数据契约中重要的属性就是DataContractAttribute和DataMemberAttribute。

    using System.Runtime.Serialization;
    
    namespace ConsoleApplication20
    {
        [DataContract]
        class Person
        {
            [DataMember(Name="Age")]
            int age;
            [DataMember(Name="Name")]
            string name;
    
            public int Age { get { return age; } set { age = value; } }
            public string Name { get { return name; } set { name = value; } }
        }
    }
    


    DataContractAttribute可以应用到枚举、结构体和类上。

    DataMemberAttribute类型可以应用到类成员和属性上。

        [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
        public sealed class DataMemberAttribute : Attribute
        {
            public DataMemberAttribute();
    
            public bool EmitDefaultValue { get; set; } //表示是否需要从序列化的数据里提取默认值。对于引用类型,默认值是null,值类型是0.
            public bool IsRequired { get; set; } //表示成员是否需要出现在序列化的数据里。
            public string Name { get; set; } //把类型成员的名字映射到序列化数据的元素上
            public int Order { get; set; } //表示元素在序列化数据里的顺序
        }


    消息契约

    所有的消息契约必须实现一个公开的、无参的构造函数

    using System;
    using System.ServiceModel;
    
    namespace ConsoleApplication20
    {
        [MessageContract(WrapperName="MyMessageContract", WrapperNamespace="http://andersoft.com/anders")]
        class MyMessageContract
        {
            [MessageHeader(Name = "reservationId", MustUnderstand = true)]
            private Int32? _reservationId;
    
            [MessageBodyMember(Name = "newDateTime")]
            private DateTime? _newDateTime;
    
            public Int32? ReservationId { get { return _reservationId; } set { _reservationId = value; } }
            public DateTime? NewDateTime { get { return _newDateTime; } set { _newDateTime = value; } }
    
            public MyMessageContract()
            { }
        }
    }
    


    操作兼容性

    WCF把这些消息分为Typed和UnTyped两大类。Typed消息包括消息契约和System.ServiceModel.Channels.Message类型,而UnTyped消息包括数据契约和其他可序列化的类型。

    using System;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    
    namespace ConsoleApplication20
    {
        [ServiceContract]
        interface IAndersService
        {
            //UnTyped Message
            [OperationContract]
            Int32? RequestReservation1(DateTime? resDateTime);
            [OperationContract(IsOneWay = true)]
            void CancelReservation1(SomeDataContract dataContract);
    
            //Typed Message
            [OperationContract]
            Int32? RequestReservation2(Message message);
            [OperationContract]
            void CancelReservation2(MyMessageContract messageContract);
        }
    
        [DataContract]
        class SomeDataContract
        { }
    }
    


    我对契约的看法

    1. 避免在数据契约和消息契约里定义方法

    2. 密封契约

    3. 使用可空类型

    9.3 从契约定义到契约对象

    WCF基础结构定义了几个可以使用反射读取契约元数据的类型。

    System.ServiceModel.Description.ContractDescription

    System.ServiceModel.Description.OperationDescription

    System.ServiceModel.Description.MessageDescription


    ContractDescription类型描述了服务中的所有操作。

    ContractDescription类型封装了一个OperationDescription和一个MessageDescription集合。

    ContractDescription类型定义个一个GetContract的工厂方法,它可以接受一个类型参数。这个类型参数会作为数据契约使用。

                ContractDescription andersServiceDescription = ContractDescription.GetContract(typeof(IAndersService));
    
                foreach (OperationDescription operationDes in andersServiceDescription.Operations)
                    Console.WriteLine(operationDes.Name);
    
                //RequestReservation1
                //CancelReservation1
                //RequestReservation2
                //CancelReservation2
  • 相关阅读:
    CSS 控制table 滑动及调整列宽等问题总结
    Java读取properties文件
    水晶报表打印
    C# 运行时序列化
    C#attribute-----------初级
    c# 单元测试工程如何取得当前项目路径
    C# 字段、属性、成员变量
    水晶报表主子报表分页问题
    从0打卡leetcode之day 3 -- 最大子序列和
    从零打卡leetcode之day 2---两数相加
  • 原文地址:https://www.cnblogs.com/jiangu66/p/2997915.html
Copyright © 2020-2023  润新知