WCF扩展系列 - 行为扩展(Behaviors)
原文地址:http://www.cnblogs.com/Creator/archive/2011/05/21/2052687.html
这个系列的第一部分将会重点关注WCF行为(behaviors),WCF提供了四种类型的行为:服务行为、终结点行为、契约行为和操作行为。这些行为的接口几乎是所有WCF的扩展入口。本篇文章只是对行为拓展讲述一些基础的铺设,具体到上面四个行为的扩展以及使用案例,将会在后续的文章中讲到.
Behaviors
上述这四个行为的所定义的接口分别是IServiceBehavior,IEndpointBehavior,IContractBehavior以及 IOperationBehavior。虽然是四个不同的接口,但它们的接口方法却基本相同,分别为 AddBindingParameters(),ApplyClientBehavior()以及ApplyDispatchBehavior()。注意,IServiceBehavior由于只能作用在服务端,因此并不包含ApplyClientBehavior()方法。
public interface I[Service/Endpoint/Contract/Operation]Behavior {
void Validate(DescriptionObject);
void AddBindingParameters(DescriptionObject, BindingParameterCollection);
void ApplyDispatchBehavior(DescriptionObject, RuntimeObject);
void ApplyClientBehavior(DescriptionObject, RuntimeObject); // not on IServiceBehavior
}
其中的方法描述如下:
- AddBindingParameters:用于向绑定元素传递自定义数据,以支持协定实现。
- Validate:用于检查服务宿主和服务说明,从而确定服务是否可成功运行。
- Apply[Client/Dispatch]Behavior:这是我们可以引用和修改WCF运行时对象的地方,也是用得最多的行为方法(大部分情况,上两个方法都会留空)。用于更改运行时属性值或插入自定义扩展对象(例如错误处理程序、消息或参数拦截器、安全扩展以及其他自定义扩展对象)。
他们各自的作用范围如下图所示(引用自张逸):
增加一个行为(behaviors )
向WCF中增加行为有三种不同的方法:
-
代码:service / endpoint / contract / operation 的描述类有一个behaviors集合属性,我们可以通过他简单的增加一个行为,具体做法,先将自定义服务行为添加到 Behaviors 属性,然后对 System.ServiceModel.ServiceHost 对象调用 ICommunicationObject.Open 方法。
-
配置文件:通过配置文件system.serviceModel/behaviors 节点,我们可以指定service behaviors 和 endpoint behaviors,已达到添加行为的目的
-
特性: 添加行为的简单方法是使用特性 — — 除了终结点行为。通过创建特性类 (基类型 = = System.Attribute) 和实现其中一个行为接口,您可以将特性应用于适当的元素,并添加行为到元素的描述。下面的代码显示了一个简单的服务,基于特性的行为的添加以及输出它们的调用顺序 (以及通过代码添加终结点行为)。
1 using System; 2 using System.Collections.ObjectModel; 3 using System.Reflection; 4 using System.ServiceModel; 5 using System.ServiceModel.Channels; 6 using System.ServiceModel.Description; 7 using System.ServiceModel.Dispatcher; 8 9 namespace Behaviors 10 { 11 class MyServiceBehaviorAttribute : Attribute, IServiceBehavior 12 { 13 public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) 14 { 15 Console.WriteLine("Inside {0}.{1}", this.GetType().Name, MethodBase.GetCurrentMethod().Name); 16 } 17 18 public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 19 { 20 Console.WriteLine("Inside {0}.{1}", this.GetType().Name, MethodBase.GetCurrentMethod().Name); 21 } 22 23 public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 24 { 25 Console.WriteLine("Inside {0}.{1}", this.GetType().Name, MethodBase.GetCurrentMethod().Name); 26 } 27 } 28 29 class MyEndpointBehavior : IEndpointBehavior 30 { 31 public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 32 { 33 Console.WriteLine("Inside {0}.{1}, endpoint {2}", this.GetType().Name, MethodBase.GetCurrentMethod().Name, endpoint.Name); 34 } 35 36 public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) 37 { 38 Console.WriteLine("Inside {0}.{1}, endpoint {2}", this.GetType().Name, MethodBase.GetCurrentMethod().Name, endpoint.Name); 39 } 40 41 public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) 42 { 43 Console.WriteLine("Inside {0}.{1}, endpoint {2}", this.GetType().Name, MethodBase.GetCurrentMethod().Name, endpoint.Name); 44 } 45 46 public void Validate(ServiceEndpoint endpoint) 47 { 48 Console.WriteLine("Inside {0}.{1}, endpoint {2}", this.GetType().Name, MethodBase.GetCurrentMethod().Name, endpoint.Name); 49 } 50 } 51 52 class MyContractBehaviorAttribute : Attribute, IContractBehavior 53 { 54 public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 55 { 56 Console.WriteLine("Inside {0}.{1}, contract {2}", this.GetType().Name, MethodBase.GetCurrentMethod().Name, contractDescription.ContractType.Name); 57 } 58 59 public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime) 60 { 61 Console.WriteLine("Inside {0}.{1}, contract {2}", this.GetType().Name, MethodBase.GetCurrentMethod().Name, contractDescription.ContractType.Name); 62 } 63 64 public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime) 65 { 66 Console.WriteLine("Inside {0}.{1}, contract {2}", this.GetType().Name, MethodBase.GetCurrentMethod().Name, contractDescription.ContractType.Name); 67 } 68 69 public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) 70 { 71 Console.WriteLine("Inside {0}.{1}, contract {2}", this.GetType().Name, MethodBase.GetCurrentMethod().Name, contractDescription.ContractType.Name); 72 } 73 } 74 75 class MyOperationBehaviorAttribute : Attribute, IOperationBehavior 76 { 77 public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) 78 { 79 Console.WriteLine("Inside {0}.{1}, operation {2}", this.GetType().Name, MethodBase.GetCurrentMethod().Name, operationDescription.Name); 80 } 81 82 public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) 83 { 84 Console.WriteLine("Inside {0}.{1}, operation {2}", this.GetType().Name, MethodBase.GetCurrentMethod().Name, operationDescription.Name); 85 } 86 87 public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) 88 { 89 Console.WriteLine("Inside {0}.{1}, operation {2}", this.GetType().Name, MethodBase.GetCurrentMethod().Name, operationDescription.Name); 90 } 91 92 public void Validate(OperationDescription operationDescription) 93 { 94 Console.WriteLine("Inside {0}.{1}, operation {2}", this.GetType().Name, MethodBase.GetCurrentMethod().Name, operationDescription.Name); 95 } 96 } 97 98 [ServiceContract] 99 [MyContractBehavior] 100 public interface ITest 101 { 102 [OperationContract] 103 [MyOperationBehavior] 104 int Add(int x, int y); 105 [OperationContract] 106 int Multiply(int x, int y); 107 } 108 109 [ServiceContract] 110 [MyContractBehavior] 111 public interface ITest2 112 { 113 [OperationContract] 114 [MyOperationBehavior] 115 string Echo(string text); 116 } 117 118 [MyServiceBehavior] 119 public class Service : ITest, ITest2 120 { 121 public int Add(int x, int y) { return x + y; } 122 public int Multiply(int x, int y) { return x * y; } 123 public string Echo(string text) { return text; } 124 } 125 126 class Program 127 { 128 static void Main(string[] args) 129 { 130 string baseAddress = "http://" + Environment.MachineName + ":8000/Service"; 131 ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress)); 132 ServiceEndpoint ep1 = host.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), "basic"); 133 ep1.Name = "Endpoint1-BasicHttp"; 134 ep1.Behaviors.Add(new MyEndpointBehavior()); 135 ServiceEndpoint ep2 = host.AddServiceEndpoint(typeof(ITest2), new WSHttpBinding(), "ws"); 136 ep2.Name = "Endpoint2-WSHttp"; 137 ep2.Behaviors.Add(new MyEndpointBehavior()); 138 Console.WriteLine("Opening the host..."); 139 host.Open(); 140 Console.WriteLine("Host opened"); 141 } 142 } 143 }
我并不认为这就是“最优”的添加方法,他只是描述通过特性增加行为的一个特定的例子而已,具体什么是“最优”的添加行为的方法呢?其实这就像软件架构一样,永远没有最好的架构,只有最合适的架构。所以具体项目里面采用哪种方式去添加来得具体情况具体分析。个人比较喜欢用使用配置文件添加的方法….
在后面的文章中将会讲诉到具体的行为扩展,敬请期待..
1.1.1. IServiceBehavior
1.1.2. IContractBehavior
1.1.3. IEndpointBehavior
1.1.4. IOperationBehavior