• 真实代理(RealProxy)在WCF中的运用


    在WCF中,当我们在调用服务端的方法时,一般有两点需要考虑:1、捕获服务端的异常信息,记录日志;2、及时关闭会话信道,当调用超时或调用失败时及时中断会话信道。我们一般会像下面这样处理(以CalculatorService为例):

    using (ChannelFactory<ICalculatorService> channelFactory = new ChannelFactory<ICalculatorService>("CalculatorService"))
                {
                    ICalculatorService proxy = channelFactory.CreateChannel();
                    var commObj = proxy as ICommunicationObject;
                     try
                         {
                        Console.WriteLine("x + y = {2} when x = {0} and y = {1}", 1, 2, proxy.Add(1, 2));
                        commObj.Close();
                         }
                      catch (CommunicationException)
                        {
                            commObj.Abort();
                        }
                        catch (TimeoutException)
                        {
                            commObj.Abort();
                        }
                        catch (Exception)
                        {
                            //TODO:记录异常到日志
                            commObj.Abort();
                            throw;
                        }
                }

    以上这种处理方式完全可以满足我们的需要,但存在一个问题,每次调用服务端的方法时都需要手工加上这些异常捕获代码,如果服务有很多方法时,这样势必会存在大量功能重复的代码,可复用性很差。我们可以借鉴一下AOP的思想,具体来说就是对服务端方法调用进行拦截。对于.Net应用来说,自定义RealProxy是实现方法调用拦截最简单的一种方式。下面是一个自定义RealProxy的例子:

    public class CalculatorServiceRealProxy : RealProxy
        {
            public CalculatorServiceRealProxy():base(typeof(ICalculatorService)){}
            public override IMessage Invoke(IMessage msg)
            {
                IMethodReturnMessage methodReturn = null;
                IMethodCallMessage methodCall = (IMethodCallMessage)msg;
                var client = new ChannelFactory<ICalculatorService>("CalculatorService");
                var channel = client.CreateChannel();
                try
                {
                   object[] copiedArgs = Array.CreateInstance(typeof(object), methodCall.Args.Length) as object[];
                    methodCall.Args.CopyTo(copiedArgs, 0);
                    object returnValue = methodCall.MethodBase.Invoke(channel, copiedArgs);
                    methodReturn = new ReturnMessage(returnValue,
                                                    copiedArgs,
                                                    copiedArgs.Length,
                                                    methodCall.LogicalCallContext,
                                                    methodCall);
                    //TODO:Write log
                }
                catch (Exception ex)
                {
                    var exception = ex;
                    if (ex.InnerException != null)
                        exception = ex.InnerException;
                    methodReturn = new ReturnMessage(exception, methodCall);
                }
                finally
                {
                    var commObj = channel as ICommunicationObject;
                    if (commObj != null)
                    {
                        try
                        {
                            commObj.Close();
                        }
                        catch (CommunicationException)
                        {
                            commObj.Abort();
                        }
                        catch (TimeoutException)
                        {
                            commObj.Abort();
                        }
                        catch (Exception)
                        {
                            commObj.Abort();
                            //TODO:Logging exception
                            throw;
                        }
                    }
                }
                return methodReturn;
            }
        }

    方法调用:

    static void Main(string[] args)
            {
    
            ICalculatorService proxy = (ICalculatorService)new CalculatorServiceRealProxy().GetTransparentProxy();
    
                Console.WriteLine("x + y = {2} when x = {0} and y = {1}", 1, 2, proxy.Add(1, 2));
                Console.WriteLine("x - y = {2} when x = {0} and y = {1}", 1, 2, proxy.Subtract(1, 2));
                Console.WriteLine("x * y = {2} when x = {0} and y = {1}", 1, 2, proxy.Multiply(1, 2));
                Console.WriteLine("x / y = {2} when x = {0} and y = {1}", 1, 2, proxy.Divide(1, 2));
    
    
                Console.ReadKey();
            }

    通过自定义的RealProxy创建TransparentProxy供客户端代码调用,对于通过TransparentProxy的每一次调用,都会被RealProxy接管,这样我们就可以在RealProxy中加入异常捕获、记录日志等非业务逻辑代码,这些代码在每次调用服务端方法时都会被调用。

    源代码下载  (工程ConsoleHosting为服务端,工程Client3为客户端)

    image

  • 相关阅读:
    错误:IIS Admin Service 服务因 2147549465 (0x80010119) 服务性错误而停止(转)
    学习:Using STSADM o migrateuser on a recreated account(转)
    记录:MOSS里中英文权限对照表
    错误:用stsdev创建的解决方案:Makecab.exe — error MSB3073
    记录:MOSS:EventHandler部署和使用
    学习:C#中的String、string(转)
    学习:SQL数据库日志收缩(转)
    学习:SharePoint 使用 SPQuery.Folder 查询文件夹中的数据(转)
    学习:双机热备、集群、负载均衡、SQL故障转移群集简单理解(转)
    学习:[SharePoint]HTTP 500 Internal Server Error (转)
  • 原文地址:https://www.cnblogs.com/parning/p/4274258.html
Copyright © 2020-2023  润新知