![](/icons/61909smhl.gif)
![](/icons/61909smhr.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909de.gif)
![](/icons/61909de.gif)
![](/icons/61909dou2.gif)
![](/icons/61909smhl.gif)
![](/icons/61909smhr.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909dou2.gif)
通过
![](/icons/61909smhl.gif)
![](/icons/61909smhr.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909dou2.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909yi.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909dou2.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909yi.gif)
![](/icons/61909chengxu.gif)
![](/icons/61909de.gif)
![](/icons/61909yi.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909yi.gif)
![](/icons/61909de.gif)
![](/icons/61909dou2.gif)
![](/icons/61909de.gif)
![](/icons/61909de.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909dou2.gif)
所以现在我们
![](/icons/61909de.gif)
![](/icons/61909de.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909dou2.gif)
![](/icons/61909yi.gif)
![](/icons/61909de.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909de.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909dou.gif)
![](/icons/61909dou2.gif)
![](/icons/61909yi.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909de.gif)
![](/icons/61909de.gif)
![](/icons/61909yi.gif)
![](/icons/61909dou2.gif)
下图所示
![](/icons/61909de.gif)
![](/icons/61909de.gif)
![](/icons/61909de.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909dou2.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909de.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909dou2.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909de.gif)
![](/icons/61909de.gif)
![](/icons/61909dou2.gif)
![](/icons/61909de.gif)
![](/icons/61909de.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909dou.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909dou.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909dou.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909dou.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909dou2.gif)
![](/icons/61909dou.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909de.gif)
![](/icons/61909de.gif)
![](/icons/61909dou2.gif)
![clip_image002 clip_image002](http://CrazyCoder.cn/WebFiles/20101/edb01932-0d7b-46d4-8def-b98c50750685.jpg)
本例仅仅是为如何通过AOP进行WCF服务
![](/icons/61909diaoyong.gif)
![](/icons/61909yi.gif)
![](/icons/61909dou.gif)
![](/icons/61909yi.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909yi.gif)
![](/icons/61909dou2.gif)
![](/icons/61909dou.gif)
![](/icons/61909yi.gif)
![](/icons/61909dou2.gif)
步骤
:创建ChannalFactory<T>
静态工厂:ChannelFactoryCreator 由于服务
通过服务代理完成
而ChannelFactory<T>是服务代理
创建者
所以在这里先定义
个ChannelFactory<T>
静态工厂类
通过它来创建或获取ChannelFactory<T>思路方法
由于ChannelFactory<T>
创建是
件费时
工作
为了提供更好
性能
和ClientBase<T>
样采用了ChannelFactory<T>
缓存Cache机制
不过
这里
缓存Cache机制比ClientBase<T>
实现要简单得多
ClientBase<T>通过终结点配置名称、终结点地址和回调对象 3者进行缓存Cache
这里仅仅是通过终结点配置名称进行ChannelFactory<T>
缓存Cache![](/icons/61909dou.gif)
我们假设客户端完全使用配置
终结点进行服务
(这也是我们推荐
使用方式)
下面是整个ChannelFactory<T>
静态工厂类
定义:
1: using
;
2: using
.Collections;
3: using
.ServiceModel;
4:
Artech.ServiceProxyFactory
5: {
6:
ernal
ChannelFactoryCreator
7: {
8: private
Hashtable channelFactories =
Hashtable
;
9:
10: public
ChannelFactory<T> Create<T>(
endpo
Name)
11: {
12:
(
.IsNullOrEmpty(endpo
Name))
13: {
14: throw
ArgumentNullException("endpo
Name");
15: }
16:
17: ChannelFactory<T> channelFactory = null;
18:
19:
(channelFactories.ContainsKey(endpo
Name))
20: {
21: channelFactory = channelFactories[endpo
Name] as ChannelFactory<T>;
22: }
23:
24:
(channelFactory
null)
25: {
26: channelFactory =
ChannelFactory<T>(endpo
Name);
27: lock (channelFactories.SyncRoot)
28: {
29: channelFactories[endpo
Name] = channelFactory;
30: }
31: }
32:
33:
channelFactory;
34: }
35: }
36: }
ChannelFactoryCreator中通过
个Hashtable类型
静态变量保存所有创建出来ChannelFactory<T>集合
Hashtable
Key为表示终结点配置名称![](/icons/61909de.gif)
串
在ChannelFactory<T>思路方法中
先通过传入
终结点配置名称查看缓存Cache中是否存在已经创建好
ChannelFactory<T>对象
如果存在则直接返回
否则创建新
ChannelFactory<T>对象,并在返回的前将其加入缓存Cache![](/icons/61909dou2.gif)
步骤 2:创建自定义RealProxy:ServiceRealProxy<T>
ServiceRealProxy<T>实现了真正
服务
、异常处理和对服务代理
关闭或中断
ServiceRealProxy<T>
构造
参数endpo
Name表示用于服务
而采用
终结点配置名称
在Invoke中
先借助于ChannelFactoryCreator获得
ChannelFactory<T>创建服务代理对象
然后通过解析参数msg(表示对思路方法![](/icons/61909de.gif)
)获得思路方法![](/icons/61909diaoyong.gif)
参数
并在try控制块中通过反射
传入参数
服务代理对象相应
思路方法
从而实现了对服务![](/icons/61909de.gif)
![](/icons/61909diaoyong.gif)
对于正常服务![](/icons/61909diaoyong.gif)
结果
将其封装成
.Runtime.Remoting.Messaging.ReturnMessage对象
并在返回的前
Close思路方法关闭服务代理![](/icons/61909dou2.gif)
在catch控制块中
对抛出
异常进行处理
由于是通过反射方式实现
思路方法![](/icons/61909diaoyong.gif)
得到
异常类型基本上都是
.Reflection.TargetInvocationException
真正进行服务![](/icons/61909diaoyong.gif)
异常被作为捕获异常
内部异常(InnerException)
所以
我们会判断内部异常是否为CommunicationException或TimeoutException
来决定是否通过
Abort思路方法强行中断服务代理
捕获
异常被封装成ReturnMessage对象返回![](/icons/61909dou2.gif)
1: using
;
2: using
.Runtime.Remoting.Messaging;
3: using
.Runtime.Remoting.Proxies;
4: using
.ServiceModel;
5:
Artech.ServiceProxyFactory
6: {
7: public
ServiceRealProxy<T>: RealProxy
8: {
9: private
_endpo
Name;
10:
11: public ServiceRealProxy(
endpo
Name):base(typeof(T))
12: {
13:
(
.IsNullOrEmpty(endpo
Name))
14: {
15: throw
ArgumentNullException("endpo
Name");
16: }
17: this._endpo
Name = endpo
Name;
18: }
19:
20: public override IMessage Invoke(IMessage msg)
21: {
22: T channel = ChannelFactoryCreator.Create<T>(this._endpo
Name).CreateChannel
;
23: IMethodCallMessage methodCall = (IMethodCallMessage)msg;
24: IMethodReturnMessage methodReturn = null;
25: object
copiedArgs = Array.CreateInstance(typeof(object), methodCall.Args.Length) as object
;
26: methodCall.Args.CopyTo(copiedArgs, 0);
27: try
28: {
29: object
Value = methodCall.MethodBase.Invoke(channel, copiedArgs);
30: methodReturn =
ReturnMessage(
Value, copiedArgs, copiedArgs.Length, methodCall.LogicalCallContext, methodCall);
31: (channel as ICommunicationObject).Close
;
32: }
33: catch (Exception ex)
34: {
35:
(ex.InnerException is CommunicationException || ex.InnerException is TimeoutException)
36: {
37: (channel as ICommunicationObject).Abort
;
38: }
39:
40:
(ex.InnerException != null)
41: {
42: methodReturn =
ReturnMessage(ex.InnerException, methodCall);
43: }
44: ![](/icons/61909else.gif)
45: {
46: methodReturn =
ReturnMessage(ex, methodCall);
47: }
48: }
49:
50:
methodReturn;
51: }
52: }
53: }
步骤 3:创建自定义服务代理工厂:ServiceProxyFactory
在本案例中
对于最终
客户端代码来说
它利用
是上面创建
自定义真实代理
透明代理间接地进行服务![](/icons/61909diaoyong.gif)
而该透明代理就是客户端
服务代理
为了便于编程
在这里我们定义
个服务代理
静态工厂类:ServiceProxyFactory
1: using
;
2:
Artech.ServiceProxyFactory
3: {
4: public
ServiceProxyFactory
5: {
6: public
T Create<T>(
endpo
Name)
7: {
8:
(
.IsNullOrEmpty(endpo
Name))
9: {
10: throw
ArgumentNullException("endpo
Name");
11: }
12:
(T)(
ServiceRealProxy<T>(endpo
Name).GetTransparentProxy
);
13: }
14: }
15: }
步骤 4:通过ServiceProxyFactory创建服务代理进行服务
由于重复繁琐
工作已经在ServiceRealProxy<T>中完成
所以客户端进行服务![](/icons/61909diaoyong.gif)
代码将会变得很简洁
为了验证在每次
完毕后
是否如我们所愿将信道关闭
我们将ServiceProxyFactory应用到我们熟悉
计算服务
例子(终结点calculatorservice配置
绑定类型为WsHttBinding)![](/icons/61909dou2.gif)
1: ICalculator calculator = ServiceProxyFactory.Create<ICalculator>("calculatorservice");
2: for (
i = 1; i < 2000; i
)
3: {
4: Console.WriteLine("{3}: x + y = {2} when x = {0} and y = {1}", 1, 2, calculator.Add(1, 2), i);
5: }
输出结果:
1 : x + y = 3 when x = 1 and y = 2
2 : x + y = 3 when x = 1 and y = 2
......
1999: x + y = 3 when x = 1 and y = 2
2000: x + y = 3 when x = 1 and y = 2
从输出
结果可以看出
2000次服务
成功完成
由此可以证明每次服务
结束后
会话信道都被成功关闭
会话信道
自动关闭或中断还带来
个好处
由于每次使用
是新信道
所以即使上
个服务
出错
也不会影响后续![](/icons/61909de.gif)
![](/icons/61909diaoyong.gif)
下面
例子证明了这
点:
1: ICalculator calculator = ServiceProxyFactory.Create<ICalculator>("calculatorservice");
2: try
3: {
4: Console.WriteLine("x / y = {2} when x = {0} and y = {1}",2,0,calculator.Divide(2,0));
5: }
6: catch(Exception ex)
7: {
8: Console.WriteLine(ex.Message);
9: }
10: Console.WriteLine("x + y = {2} when x = {0} and y = {1}",2,0,calculator.Add(2,0));
输出结果:
The server was unable to process the request due to an
ernal error. For more information about the error, either turn _disibledevent=>
x + y = 2 when x = 2 and y = 0
作者:Artech
出处:http://artech.cnblogs.com
本文版权归作者和博客园共有
欢迎转载
但未经作者同意必须保留此段声明
且在文章页面明显位置给出原文连接
否则保留追究法律责任
权利
Tag标签: WCF,Exception Handling,AOP,RealProxy,TransparentProxy
延伸阅读
![](/icons/61909de.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909de.gif)
![](/icons/61909dou2.gif)
![](/icons/61909de.gif)
![](/icons/61909hanshu.gif)
![](/icons/61909int.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909de.gif)
![](/icons/61909dou2.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909dou2.gif)
![](/icons/61909de.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909dou.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909dou2.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909System.gif)
![](/icons/61909dou.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909dou2.gif)
在catch控制块中
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909System.gif)
![](/icons/61909dou.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909de.gif)
![](/icons/61909de.gif)
![](/icons/61909dou2.gif)
![](/icons/61909dou.gif)
![](/icons/61909dou.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909dou2.gif)
![](/icons/61909de.gif)
![](/icons/61909dou2.gif)
1: using
![](/icons/61909System.gif)
2: using
![](/icons/61909System.gif)
3: using
![](/icons/61909System.gif)
4: using
![](/icons/61909System.gif)
5:
![](/icons/61909namespace.gif)
6: {
7: public
![](/icons/61909class.gif)
8: {
9: private
![](/icons/61909string.gif)
![](/icons/61909int.gif)
10:
11: public ServiceRealProxy(
![](/icons/61909string.gif)
![](/icons/61909int.gif)
12: {
13:
![](/icons/61909if.gif)
![](/icons/61909string.gif)
![](/icons/61909int.gif)
14: {
15: throw
![](/icons/61909new.gif)
![](/icons/61909int.gif)
16: }
17: this._endpo
![](/icons/61909int.gif)
![](/icons/61909int.gif)
18: }
19:
20: public override IMessage Invoke(IMessage msg)
21: {
22: T channel = ChannelFactoryCreator.Create<T>(this._endpo
![](/icons/61909int.gif)
![](/icons/61909kh.gif)
23: IMethodCallMessage methodCall = (IMethodCallMessage)msg;
24: IMethodReturnMessage methodReturn = null;
25: object
![](/icons/61909zhk2.gif)
![](/icons/61909zhk2.gif)
26: methodCall.Args.CopyTo(copiedArgs, 0);
27: try
28: {
29: object
![](/icons/61909return.gif)
30: methodReturn =
![](/icons/61909new.gif)
![](/icons/61909return.gif)
31: (channel as ICommunicationObject).Close
![](/icons/61909kh.gif)
32: }
33: catch (Exception ex)
34: {
35:
![](/icons/61909if.gif)
36: {
37: (channel as ICommunicationObject).Abort
![](/icons/61909kh.gif)
38: }
39:
40:
![](/icons/61909if.gif)
41: {
42: methodReturn =
![](/icons/61909new.gif)
43: }
44:
![](/icons/61909else.gif)
45: {
46: methodReturn =
![](/icons/61909new.gif)
47: }
48: }
49:
50:
![](/icons/61909return.gif)
51: }
52: }
53: }
步骤 3:创建自定义服务代理工厂:ServiceProxyFactory
在本案例中
对于最终
客户端代码来说
它利用
是上面创建
自定义真实代理
透明代理间接地进行服务![](/icons/61909diaoyong.gif)
而该透明代理就是客户端
服务代理
为了便于编程
在这里我们定义
个服务代理
静态工厂类:ServiceProxyFactory
1: using
;
2:
Artech.ServiceProxyFactory
3: {
4: public
ServiceProxyFactory
5: {
6: public
T Create<T>(
endpo
Name)
7: {
8:
(
.IsNullOrEmpty(endpo
Name))
9: {
10: throw
ArgumentNullException("endpo
Name");
11: }
12:
(T)(
ServiceRealProxy<T>(endpo
Name).GetTransparentProxy
);
13: }
14: }
15: }
步骤 4:通过ServiceProxyFactory创建服务代理进行服务
由于重复繁琐
工作已经在ServiceRealProxy<T>中完成
所以客户端进行服务![](/icons/61909diaoyong.gif)
代码将会变得很简洁
为了验证在每次
完毕后
是否如我们所愿将信道关闭
我们将ServiceProxyFactory应用到我们熟悉
计算服务
例子(终结点calculatorservice配置
绑定类型为WsHttBinding)![](/icons/61909dou2.gif)
1: ICalculator calculator = ServiceProxyFactory.Create<ICalculator>("calculatorservice");
2: for (
i = 1; i < 2000; i
)
3: {
4: Console.WriteLine("{3}: x + y = {2} when x = {0} and y = {1}", 1, 2, calculator.Add(1, 2), i);
5: }
输出结果:
1 : x + y = 3 when x = 1 and y = 2
2 : x + y = 3 when x = 1 and y = 2
......
1999: x + y = 3 when x = 1 and y = 2
2000: x + y = 3 when x = 1 and y = 2
从输出
结果可以看出
2000次服务
成功完成
由此可以证明每次服务
结束后
会话信道都被成功关闭
会话信道
自动关闭或中断还带来
个好处
由于每次使用
是新信道
所以即使上
个服务
出错
也不会影响后续![](/icons/61909de.gif)
![](/icons/61909diaoyong.gif)
下面
例子证明了这
点:
1: ICalculator calculator = ServiceProxyFactory.Create<ICalculator>("calculatorservice");
2: try
3: {
4: Console.WriteLine("x / y = {2} when x = {0} and y = {1}",2,0,calculator.Divide(2,0));
5: }
6: catch(Exception ex)
7: {
8: Console.WriteLine(ex.Message);
9: }
10: Console.WriteLine("x + y = {2} when x = {0} and y = {1}",2,0,calculator.Add(2,0));
输出结果:
The server was unable to process the request due to an
ernal error. For more information about the error, either turn _disibledevent=>
x + y = 2 when x = 2 and y = 0
作者:Artech
出处:http://artech.cnblogs.com
本文版权归作者和博客园共有
欢迎转载
但未经作者同意必须保留此段声明
且在文章页面明显位置给出原文连接
否则保留追究法律责任
权利
Tag标签: WCF,Exception Handling,AOP,RealProxy,TransparentProxy
延伸阅读
![](/icons/61909diaoyong.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909de.gif)
![](/icons/61909dou2.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909dou.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909de.gif)
![](/icons/61909de.gif)
![](/icons/61909dou2.gif)
1: ICalculator calculator = ServiceProxyFactory.Create<ICalculator>("calculatorservice");
2: for (
![](/icons/61909int.gif)
![](/icons/61909jiajia.gif)
3: {
4: Console.WriteLine("{3}: x + y = {2} when x = {0} and y = {1}", 1, 2, calculator.Add(1, 2), i);
5: }
输出结果:
1 : x + y = 3 when x = 1 and y = 2
2 : x + y = 3 when x = 1 and y = 2
......
1999: x + y = 3 when x = 1 and y = 2
2000: x + y = 3 when x = 1 and y = 2
从输出
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909dou.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909dou.gif)
![](/icons/61909dou2.gif)
![](/icons/61909de.gif)
![](/icons/61909yi.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909dou.gif)
![](/icons/61909yi.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909diaoyong.gif)
![](/icons/61909dou2.gif)
![](/icons/61909de.gif)
![](/icons/61909yi.gif)
1: ICalculator calculator = ServiceProxyFactory.Create<ICalculator>("calculatorservice");
2: try
3: {
4: Console.WriteLine("x / y = {2} when x = {0} and y = {1}",2,0,calculator.Divide(2,0));
5: }
6: catch(Exception ex)
7: {
8: Console.WriteLine(ex.Message);
9: }
10: Console.WriteLine("x + y = {2} when x = {0} and y = {1}",2,0,calculator.Add(2,0));
输出结果:
The server was unable to process the request due to an
![](/icons/61909int.gif)
x + y = 2 when x = 2 and y = 0
作者:Artech
出处:http://artech.cnblogs.com
本文版权归作者和博客园共有
![](/icons/61909dou.gif)
![](/icons/61909dou.gif)
![](/icons/61909dou.gif)
![](/icons/61909dou.gif)
![](/icons/61909de.gif)
![](/icons/61909dou2.gif)
Tag标签: WCF,Exception Handling,AOP,RealProxy,TransparentProxy
最新评论