终于我又看完了二期爱情保卫战,太酸爽了,推荐链接:[http://www.iqiyi.com/a_19rrgublqh.html?vfm=2008_aldbd](http://www.iqiyi.com/a_19rrgublqh.html?vfm=2008_aldbd),不多说,谁看谁入迷,下面言归正传,
看看这个很有意思的Behavior。
## 一: Behavior这个泼妇的厉害
在前面的文章中,我也清楚的说明了整个wcf通信流,而Behavior这个泼妇可以在wcf通信流中的任何地方插上一脚,蛮狠无比,利用的好,让你上天堂,利用的不
好,让你下地狱。。。下面让你看看behavior到底有哪些可以注入的点???先画个简图:![](https://box.kancloud.cn/2015-08-04_55c0b4ecf236b.png)
上面的图,大概就是wcf的通信简图,所有蓝色字体都是Behavior注入的点,其中Client和Service端都可以注入,如果按照功能分的话,又可以分为“操作级别”和
”端点级别“,下面我来简要的分解下。
## 二:端点级别Behavior
从图中你也可以看到,消息检查器是放在Channel这个级别的,也就是说它可以监视Client和Server的入站请求,也就是说所有的请求都需要通过它转发,如果
这样的话,那我是不是可以在这个注入点上自由的修改,变更,拦截入站和出站请求,而且利用这个特性我还可以做很多的事情,比如日志记录,记录统计等等,下
面我们来看看这个怎么使用??? 只需要extends IEndpointBehavior 和 IDispatchMessageInspector,然后加入EndpointBehaviors即可。。。
1. IDispatchMessageInspector
~~~
public class MyDispatchMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
Console.WriteLine(request.ToString());
return request;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
Console.WriteLine(reply.ToString());
}
}
~~~
2. IEndpointBehavior
~~~
public class MyEndpointBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MyDispatchMessageInspector());
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
~~~
3\. 将MyEndpointBehavior加入到Host中
~~~
static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(HomeService), new Uri("http://127.0.0.1:1920"));
host.AddServiceEndpoint(typeof(IHomeService), new BasicHttpBinding(), "HomeServie");
host.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpGetEnabled = true });
host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
host.Description.Endpoints[0].EndpointBehaviors.Add(new MyEndpointBehavior());
host.Open();
Console.WriteLine("服务已经开启!!!");
Console.Read();
}
~~~
4\. 最后我们看一下服务方法
~~~
public class HomeService : IHomeService
{
public string Update(string message)
{
Console.WriteLine("我在Action方法:" + message);
return "my reply!!!";
}
}
~~~
下面看看效果。。。在效果图中,你应该看到了。在我的Action中的方法前后各有一段“入站消息”和“出站消息”,是不是很爽???
![](https://box.kancloud.cn/2015-08-04_55c0b4eeb97e7.png)
## 三:操作级别Behavior
从文章开头的简图中,你应该看到了,Operation级别的Behavior比较多,有“操作启动器(IOperationInvoker)","参数检查(IParameterInspector)“,
“消息格式化器(IDispatchMessageFormatter)”等等。。。 为什么说等等这个词,很简单啊,,,其实还有很多系统内置的,既然是Operation,那就必
然是针对方法的,还记得OperationContract是怎么套在方法上的吗??? 是特性,对吧,,,同样的道理,OperationBehavior也是一样,那怎么用呢??
同样也是很简单的,继承几个接口即可。。。
IParameterInspector 的玩法
其实没什么好说的,既然是属于Operation下面的Behavior,那都是通过特性注入的,而这个IParameterInspector,可以做到类似Mvc的Model验证,下面
我做个简单的Action参数长度验证(长度不超过8个字符)。
1. IParameterInspector
~~~
public class MyIParameterInspector : IParameterInspector
{
public int MaxLength { get; set; }
public MyIParameterInspector(int MaxLength)
{
this.MaxLength = MaxLength;
}
/// <summary>
/// 出站的操作
/// </summary>
/// <param name="operationName"></param>
/// <param name="outputs"></param>
/// <param name="returnValue"></param>
/// <param name="correlationState"></param>
public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
{
}
/// <summary>
/// 入站的参数
/// </summary>
/// <param name="operationName"></param>
/// <param name="inputs"></param>
/// <returns></returns>
public object BeforeCall(string operationName, object[] inputs)
{
foreach (var item in inputs)
{
if (Convert.ToString(item).Length > MaxLength)
{
throw new Exception("码单,长度不能超过 " + MaxLength + " 个长度");
}
}
return null;
}
}
~~~
2. IOperationBehavior
~~~
public class MyOperationBehavior : Attribute, IOperationBehavior
{
public int MaxLength { get; set; }
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
{
}
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
dispatchOperation.ParameterInspectors.Add(new MyIParameterInspector(MaxLength));
}
public void Validate(OperationDescription operationDescription)
{
}
}
~~~
3\. 在Action在加上MyOperationBehavior 这个 Attribute
~~~
public class HomeService : IHomeService
{
[MyOperationBehavior(MaxLength = 5)]
public string Update(string message)
{
Console.WriteLine("我在Action方法:" + message);
return "my reply!!!";
}
}
~~~
4\. 然后我在客户端故意输入大于5的字符,看看效果怎么样???
~~~
public class Program1
{
static void Main(string[] args)
{
HomeServiceClient client = new HomeServiceClient();
client.Update("我故意输入了很多的字符,哈哈。。。。。");
Console.Read();
}
}
~~~
5\. 最后看看效果图,可以看到,最终的入站消息会抛出一个异常。。。
![](https://box.kancloud.cn/2015-08-04_55c0b4f128e9e.png)
MessageFormatter,IOperationInvoker 的玩法
剩下的这两个玩法都差不多,你只需要extends一下,然后加入到OperationBehavior即可,有了上面的思想,我想下面这些使用起来都不是问题吧。。。
- 第一天 三种Binding让你KO80%的业务
- 第二天 告别烦恼的config配置
- 第三天 client如何知道server提供的功能清单
- 第四天 你一定要明白的通信单元Message
- 第五天 你需要了解的三个小技巧
- 第六天 你必须要了解的3种通信模式
- 第七天 Close和Abort到底该怎么用才对得起观众
- 第八天 对“绑定”的最后一点理解
- 第九天 高级玩法之自定义Behavior
- 第十天 学会用SvcConfigEditor来简化配置
- 第十一天 如何对wcf进行全程监控
- 第十二天 说说wcf中的那几种序列化
- 第十三天 用WCF来玩Rest
- 第十四天 一起聊聊FaultException
- 终结篇 那些你需要注意的坑