一、摘要
由於公司需要使用WCF進行分布式開發,剛剛可以借用這個時候學學WCF了,隨便在博客上記錄下在項目中用到WCF的那些功能寫的內容可能不全但是都是在項目中能用的實用的WCF功能點和技術。
下面引用網絡上一長圖片具體在那里看到的已經忘記了。
![]()
下面引用網絡上的一段話來描述這個圖:
在宿主進程嵌入了一個或者多個服務,服務通過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
如:[ServiceContract(Name = "HeatingManagerService",Namespace= "http://www.cnblogs.com/luomingui")]
public interface IHeatingManagerBase { ....... }[OperationContract](方法的設計)
服務契約中的所有方法都應該擁有 OperationContract能夠顯式地指定 Name , Action , ReplyAction![]()
如:
[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
如:[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的類型的對象可以被傳送,且只有成員屬性會被傳遞,成員方法不會被傳遞。
如:[System.Runtime.Serialization.DataContract(Namespace = "http://schemas.thatindigogirl.com/samples/2006/06")]public class DeviceHCV03HisInfoEntity : BaseClass<DeviceHCV03HisInfoEntity>{.....}
四、WCF契約設計 -- 契約示例
已知類型在服務契約中使用多態的行為'
在服務操作中暴露基本類型將已知類型相關到(基本類型,特定操作,整個服務契約)
采用屬性聲明或者配置的方式來實現想我們常用的實體類就是
KnownType
已知類型契約(KnownTypesContract) 示例:
1: [ServiceContract]2: public interface IService13: {
4: [OperationContract]5: [ServiceKnownType(typeof(SexBoy))]//通過接口文件方法中添加 SexType 標ê記實現多態。6: void GetSex(SexType sex);7: }
8:
9: public class Service1 : IService110: {
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 UserInfoEntity37: {
38: [DataMember(Name = "IdContract", IsRequired = false, Order = 0)]39: public string Id40: {
41: get;42: set;43: }
44: [DataMember(Name = "NameContract", IsRequired = false, Order = 1)]45: public string Name46: {
47: get;48: set;49: }
50: [DataMember(Name = "SexContract", IsRequired = false, Order = 2)]51: public virtual SexType Sex52: {
53: get;54: set;55: }
56:
57: }
58:
59: [DataContract]60: public class SexBoy : UserInfoEntity61: {
62: public SexBoy()63: {
64:
65: }
66:
67: [DataMember(Name = "SexCategories", IsRequired = true, Order = 3)]68: public override SexType Sex69: {
70: get { return SexType.boy; }71: }
72:
73: }
74:
75: [DataContract]76: public enum SexType77: {
78: [EnumMember]79: boy = 0,
80: [EnumMember]81: girl = 1,
82: }
83:
消息契約(MessageContract)
• 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, ProtectionLevel1: [ServiceContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)]2: public interface IService23: {4: [OperationContract]5: SaveResponse SaveItem(SaveRequest requestMessage);6: [OperationContract]7: GetResponse GetItem(GetRequest requestMessage);8: }
9:
10: public class Service2 : IService211: {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 SaveRequest37: {38: [MessageBodyMember]39: public UserInfoEntity Item { get; set; }40: }
41:
42: [MessageContract(IsWrapped = false)]43: public class SaveResponse44: {45: }
46:
47: [MessageContract(IsWrapped = false)]48: public class GetRequest49: {50: [MessageHeader]51: public string LicenseKey { get; set; }52: }
53:
54: [MessageContract(IsWrapped = false)]55: public class GetResponse56: {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: #endregion70:
消息契約注意:
配置文件注意的地方 權限應為 Message
![]()
五、WCF契約設計 -- 契約總結
服務契約定義可用的操作和簽名數據契約和其他可序列化的類型能夠包含在服務契約中已知類型,允許多態契約
三、WCF契約設計 -- 資料
MSDN
http://social.msdn.microsoft.com/Forums/zh-CN/wcfzhchs/thread/4c483f01-2e59-4b67-9426-10e9746d0b93