一、摘要
由于公司需要使用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 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)
• 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:
消息契约注意:
配置文件注意的地方 权限应为 Message
五、WCF契约设计 -- 契约总结
服务契约定义可用的操作和签名
数据契约和其他可序列化的类型能够包含在服务契约中
已知类型,允许多态契约
三、WCF契约设计 -- 资料
MSDN
http://social.msdn.microsoft.com/Forums/zh-CN/wcfzhchs/thread/4c483f01-2e59-4b67-9426-10e9746d0b93