Go to my github

WCF 开发日志 -- WCF契约设计

一、摘要

        

          由于公司需要使用WCF进行分布式开发,刚刚可以借用这个时候学学WCF了,随便在博客上记录下在项目中用到WCF的那些功能写的内容可能不全但是都是在项目中能用的实用的WCF功能点和技术。

         下面引用网络上一长图片具体在那里看到的已经忘记了。

          %E5%9B%9E%E9%A1%BE 

          下面引用网络上的一段话来描述这个图:        

            在宿主进程嵌入了一个或者多个服务,服务通过EndPoint也就是端点对外进行暴露,在客户端进程如果想获取宿主进程当中的服务,需要一个Proxy也就是代理,客户端进程如果说现在需要获取宿主进程当中的某一个服务的话,客户端把要求提交给代理,然后通过代理封装到EndPoint当中,再通过Message也就是消息的方式传到宿主进程当中的EndPoint,在提交到Service当中去处理,处理完毕在经过一个反向的过程。

 

二、本文大纲

     

       a、摘要  。

       b、WCF契约设计 -- 契约知识 。

       c、WCF契约设计 -- 契约示例 。

       d、WCF契约设计 -- 契约总结。

       e、WCF契约设计 -- 目前还没有用的。

 
三、WCF契约设计 -- 契约知识

      

在WCF当中服务契约是通过属性的方式来定义的,也就是我们希望在服务这一端暴露服务给客户端,我们可以在这些服务上面我们通过添加ServiceContract和OperationContract这样的属性,在以前我们开发WebService的时候要想给外界暴露一些Web方法的话需要添加WebMethod标记,ServiceContract和OperationContract的添加和WebMethod的添加是类似的效果
 

   面向对象设计原则OO:

 

<1>单一职责原则(SRP): 一个类应当仅有一个引起它变更的原因。

  <2>开放封闭原则(OCP): 类模块应当是可扩大的,然则不成批改(对扩大开放,对更改封闭)。

  <3>Liskov 调换原则(LSP): 子类必须可以或许调换它们的基类。

  <4> 依附倒置原则(DIP): 高层模块不该该依附于低层模块,二者都应当依附于抽象。 抽象不该该依附于实现细节,实现细节应当依附于抽象。

  <5>接口隔离原则(ISP): 不该该强迫客户法度依附于它们不消的办法。

   接口时辰即遵守单一职责和接口隔离等原则,又要推敲体系的开辟本钱。公道的接口是专业的、松耦合的、规矩化和可重用的接口

接口分发原则

      [ServiceContract] (接口或类的设计应该征询OOP)

 
应用于接口或者类中
建议应用于接口中
    消除服务实现的耦合性
    服务可能会实现多于1个契约
总是提供有意义的命名空间
能够显式地指定Name
 image 
如:
[ServiceContract(Name = "HeatingManagerService",  
Namespace= "http://www.cnblogs.com/luomingui")]    
public interface IHeatingManagerBase    { ....... } 

[OperationContract](方法的设计)

服务契约中的所有方法都应该拥有 OperationContract
能够显式地指定 Name , Action , ReplyAction
 image 

如:

 [OperationContract(Name = "AddHouseHoldInfo", Action = "http://www.cnblogs.com/luomingui/AddHouseHoldInfo",  ReplyAction = "http://www.cnblogs.com/luomingui/AddHouseHoldInfoResponse")]      
  bool AddHouseHoldInfo(RequestHeader request, HouseHoldInfoEntity model);   

 

   [DataMember] (实体类的设计)

实体类中所有的字段都应该拥有DataMember
能够显式指定 Name , IsRequired , Order
image 
如:
[DataMember(Name = "AreaId", IsRequired = false, Order = 0)]
public Guid AreaId{ get;  set; }
[DataMember(Name = "Id", IsRequired = false, Order = 1)]
public Guid Id{ get;  set; } 
 
    [DataContract] (实体类的设计) 
    只有声明为DataContract的类型的对象可以被传送,且只有成员属性会被传递,成员方法不会被传递。
 image 
如:
[System.Runtime.Serialization.DataContract(Namespace = "http://schemas.thatindigogirl.com/samples/2006/06")]
public class DeviceHCV03HisInfoEntity : BaseClass<DeviceHCV03HisInfoEntity>
{.....}
 
四、WCF契约设计 -- 契约示例

 

已知类型在服务契约中使用多态的行为'

在服务操作中暴露基本类型将已知类型相关到(基本类型,特定操作,整个服务契约)

采用属性声明或者配置的方式来实现想我们常用的实体类就是

KnownType

image

已知类型契约(KnownTypesContract)  示例:

 1:  [ServiceContract]
 2:  public interface IService1
 3:  {
 4:      [OperationContract]
 5:      [ServiceKnownType(typeof(SexBoy))]//通过接口文件方法中添加 SexType 标ê记实现多态。        
 6:      void GetSex(SexType sex);
 7:  }
 8:   
 9:  public class Service1 : IService1
10:  {
11:      public void GetSex(SexType sex)
12:      {
13:          string strSex = "";
14:          switch (sex)
15:          {
16:              case SexType.boy:
17:                  strSex = "男";
18:                  break;
19:              case SexType.girl:
20:                  strSex = "女";
21:                  break;
22:          }
23:      }
24:  }
33:  
34:  [DataContract]
35:  [KnownType(typeof(SexBoy))]//通过基类添加 KnowType 标记实现多态
36:  public class UserInfoEntity
37:  {
38:      [DataMember(Name = "IdContract", IsRequired = false, Order = 0)]
39:      public string Id
40:      {
41:          get;
42:          set;
43:      }
44:      [DataMember(Name = "NameContract", IsRequired = false, Order = 1)]
45:      public string Name
46:      {
47:          get;
48:          set;
49:      }
50:      [DataMember(Name = "SexContract", IsRequired = false, Order = 2)]
51:      public virtual SexType Sex
52:      {
53:          get;
54:          set;
55:      }
56:   
57:  }
58:   
59:  [DataContract]
60:  public class SexBoy : UserInfoEntity
61:  {
62:      public SexBoy()
63:      {
64:   
65:      }
66:   
67:      [DataMember(Name = "SexCategories", IsRequired = true, Order = 3)]
68:      public override SexType Sex
69:      {
70:          get { return SexType.boy; }
71:      }
72:   
73:  }
74:   
75:  [DataContract]
76:  public enum SexType
77:  {
78:      [EnumMember]
79:      boy = 0,
80:      [EnumMember]
81:      girl = 1,
82:  }
83:   

 

消息契约(MessageContract) 
image  
  • MessageContractAttribute        
 – 对控制消息头和消息体元素提供了强力支持       
• 所支持的属性:         
– MessageHeaderAttribute         
– MessageBodyMemberAttribute        
 – 凡是有[MessageHeader]或[MessageBody]的那些属性,它们就是在客户端调用服务相应方法的参数。      
 • 用于:         
– 添加自定义头(custom headers)         
– 控制消息是否被包装         
– 控制签名与加密       [MessageContract]:         
• 将一个类型转换为SOAP消息         
– 类型可以包含消息头和消息体的元素         
• 能够设置IsWrapped, ProtectionLevel         
• 可以设置显式Name, Namespace         
如下面的代码:         
[MessageContract(IsWrapped=true, ProtectionLevel=ProtectionLevel.Sign)]         
public class SaveLinkRequest         {…}         
[MessageContract]         public class SaveLinkResponse         {…}        
[MessageHeader]:         
• 应用到消息契约的域(fields)或者(         properties)        
 – 为创建自定义头提供了简单的方法        
 • 能够提供Name, Namespace, ProtectionLevel        
 • 可以设置SOAP协议的设置:Relay, Actor,MustUnderstand         
[MessageBody]:        
 • 应用到消息契约的域(fields)或者属性(properties)        
 • 能够拥有多个body元素         
– 等价于在操作中拥有多个参数         
– 返回多个复杂类型数据的唯一方法        
 • 总是提供顺序(Order)         
• 可以设置Name, Namespace, ProtectionLevel
 1:      [ServiceContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
 2:      public interface IService2
 3:      {
 4:          [OperationContract]
 5:          SaveResponse SaveItem(SaveRequest requestMessage);
 6:          [OperationContract]
 7:          GetResponse GetItem(GetRequest requestMessage);
 8:      }
 9:   
10:      public class Service2 : IService2
11:      {
12:          private UserInfoEntity _item;
13:   
14:          public SaveResponse SaveItem(SaveRequest requestMessage)
15:          {
16:              this._item = requestMessage.Item;
17:              return new SaveResponse();
18:          }
19:   
20:          public GetResponse GetItem(GetRequest requestMessage)
21:          {
22:              if (requestMessage.LicenseKey != "lmg")
23:              {
24:                  throw new FaultException("Invalid license key.");
25:              }
26:              _item.Id = "001";
27:              _item.Name = "lmg";
28:              _item.Sex = SexType.boy;
29:   
30:              return new GetResponse(_item);
31:          }
32:      }
33:   
34:      #region 消息契约
35:      [MessageContract(IsWrapped = true, ProtectionLevel = ProtectionLevel.EncryptAndSign)]
36:      public class SaveRequest
37:      {
38:          [MessageBodyMember]
39:          public UserInfoEntity Item { get; set; }
40:      }
41:   
42:      [MessageContract(IsWrapped = false)]
43:      public class SaveResponse
44:      {
45:      }
46:   
47:      [MessageContract(IsWrapped = false)]
48:      public class GetRequest
49:      {
50:          [MessageHeader]
51:          public string LicenseKey { get; set; }
52:      }
53:   
54:      [MessageContract(IsWrapped = false)]
55:      public class GetResponse
56:      {
57:          public GetResponse()
58:          {
59:          }
60:   
61:          public GetResponse(UserInfoEntity item)
62:          {
63:              this.Item = item;
64:          }
65:   
66:          [MessageBodyMember]
67:          public UserInfoEntity Item { get; set; }
68:      }
69:      #endregion
70:  

消息契约注意:

       image

       配置文件注意的地方 权限应为 Message

image 

 

五、WCF契约设计 -- 契约总结
服务契约定义可用的操作和签名
数据契约和其他可序列化的类型能够包含在服务契约中
已知类型,允许多态契约
三、WCF契约设计 -- 资料  

 

MSDN

http://social.msdn.microsoft.com/Forums/zh-CN/wcfzhchs/thread/4c483f01-2e59-4b67-9426-10e9746d0b93

posted @ 2012-08-23 22:53  峡谷少爷  阅读(3675)  评论(0编辑  收藏  举报