一、摘要
由于公司需要使用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