zoukankan      html  css  js  c++  java
  • 泛型委托在项目中的应用

         感悟:对泛型委托基本属于有点认识,但从来没真正在项目中使用过,有时感觉没有合适的场景应用,但看了artech兄的文章,我才明白,原来泛型委托真的可以做很多事情,而且效果往往是没有使用委托所达不到的。

        Action<T> 泛型委托:封装一个方法,该方法只采用一个参数并且不返回值。可以使用此委托以参数形式传递方法,而不用显式声明自定义的委托。该方法必须与此委托定义的方法签名相对应。也就是说,封装的方法必须具有一个通过值传递给它的参数,并且不能返回值。当然泛型委托不只是只能支持一个参数,它最多可以支持四个参数。  

       泛型委托与直接显示声明自定义委托的示例比较:

          1:显示声明自定义委托:

    代码
    delegate void DisplayMessage(string message);
    public class TestCustomDelegate
    {
       
    public static void Main()
       {
          DisplayMessage messageTarget; 
          messageTarget 
    = ShowWindowsMessage;
          messageTarget(
    "Hello, World!");   
       }      
       
    private static void ShowWindowsMessage(string message)
       {
          MessageBox.Show(message);      
       }
    }

      

          2: Action<T> 用法。比起自定义委托,明显可以看出代码简洁了。

    代码
    public class TestAction1
    {
       
    public static void Main()
       {
          Action
    <string> messageTarget; 
         messageTarget 
    = ShowWindowsMessage;
          messageTarget(
    "Hello, World!");   
       }      
       
    private static void ShowWindowsMessage(string message)
       {
          MessageBox.Show(message);      
       }
    }

        Func<T, TResult> 委托:封装一个具有一个参数并返回 TResult 参数指定的类型值的方法。同理,这里的泛型委托只是接受一个参数的委托,它最多同样支持四个参数。TResult:此委托封装的方法的返回值类型。


        问题:目前本公司在写程序时,都使用了log4net,我想大家在做异常时,都会利用try catch来捕获异常,日志就在catch块中完成,但每个方法都写一堆的try catch往往显的有点别扭。虽然写程序时提倡尽量去捕获具体的错误异常,但总会有你预想不到的异常抛出,为此直接捕获Exception算是不错的做法。

        具体场景:在客户端调用WCF服务时,我们都需要在客户做异常处理,最常见的错误异常为CommunicationException,TimeoutException,Exception示例如下:

                

    代码
    try
                {
                    
    //执行方法调用 
                    ......
                    (proxy 
    as ICommunicationObject).Close();
                }
                
    catch (CommunicationException ex)
                {
                    (proxy 
    as ICommunicationObject).Abort();

                    WebLog.SquareLog.CommonLogger.Error(
    "取积分广场首页酒店数据异常CommunicationException:" + ex.ToString());
                }
                
    catch (TimeoutException ex)
                {
                    (proxy 
    as ICommunicationObject).Abort();
                    WebLog.SquareLog.CommonLogger.Error(
    "取积分广场首页酒店数据超时TimeoutException:" + ex.ToString());
                }
                
    catch (Exception ex)
                {      
                    (proxy 
    as ICommunicationObject).Close();      
                    WebLog.SquareLog.CommonLogger.Error(
    "取积分广场首页酒店数据异常Exception:" + ex.ToString());
                }

      

          但如果这种代码遍布整个项目,我想就有重构的必要了,因为项目中最好不要出现类似复制的代码出现,为此我们可以采用Invoke形式来重构我们已有代码,下面给出两个方法,一个是没有返回值的,一个是有值的。
        

    代码
    public static void Invoke<TContract>(TContract proxy, Action<TContract> action)
            {
                
    try
                {
                    action(proxy);
                    (proxy 
    as ICommunicationObject).Close();
                }
                
    catch (CommunicationException ex)
                {
                    (proxy 
    as ICommunicationObject).Abort();
                    WebLog.SquareLog.CommonLogger.Error(
    "取积分广场首页酒店数据异常CommunicationException:" + ex.ToString());
                }
                
    catch (TimeoutException ex)
                {
                    (proxy 
    as ICommunicationObject).Abort();
                    WebLog.SquareLog.CommonLogger.Error(
    "取积分广场首页酒店数据超时TimeoutException:" + ex.ToString());
                }
                
    catch (Exception ex)
                {        
                    (proxy 
    as ICommunicationObject).Close();      
                    WebLog.SquareLog.CommonLogger.Error(
    "取积分广场首页酒店数据异常Exception:" + ex.ToString());
                }
            }
            
    public static TReturn Invoke<TContract, TReturn>(TContract proxy, Func<TContract, TReturn> func)
            {
                TReturn returnValue 
    = default(TReturn);
                
    try
                {
                    returnValue 
    = func(proxy);
                }
                
    catch (CommunicationException ex)
                {
                    (proxy 
    as ICommunicationObject).Abort();

                    WebLog.SquareLog.CommonLogger.Error(
    "取积分广场首页酒店数据异常CommunicationException:" + ex.ToString());
                }
                
    catch (TimeoutException ex)
                {
                    (proxy 
    as ICommunicationObject).Abort();

                    WebLog.SquareLog.CommonLogger.Error(
    "取积分广场首页酒店数据超时TimeoutException:" + ex.ToString());
                }
                
    catch (Exception ex)
                {
                    WebLog.SquareLog.CommonLogger.Error(
    "取积分广场首页酒店数据异常Exception:" + ex.ToString());
                }
                
    return returnValue;
            }

          如何调用:可以看出客户端代码已经变成一条简洁代码了,它即完成了完整的异常处理,而且也把所有能够捕获的异常信息记录下来。
          

    list = ErrorHandler.Invoke<ISearchHotelForSquare, List<HotelGenericInfo>>(cli, proxy => proxy.GetHotelGenericListForSquare(requestInfo).ToList()); 

         说明:至于Invoke的应用,在System .Runtime .Remoting.Proxies有一个RealProxy,可以称做真正代理,里面有IMessage Invoke(System.Runtime.Remoting.Messaging.IMessage msg)方法:只不过这里面没有应用泛型委托。
           

    代码
            // 返回结果:
            
    //     The message returned by the invoked method, containing the return value and
            
    //     any out or ref parameters.
            public abstract IMessage Invoke(IMessage msg);
  • 相关阅读:
    11111 Generalized Matrioshkas
    Uva 442 Matrix Chain Multiplication
    Uva 10815 Andy's First Dictionary
    Uva 537 Artificial Intelligence?
    Uva 340 MasterMind Hints
    SCAU 9508 诸葛给我牌(水泥题)
    Uva 10420 List of Conquests(排序水题)
    Uva 409 Excuses, Excuses!
    10/26
    11/2
  • 原文地址:https://www.cnblogs.com/ASPNET2008/p/1704405.html
Copyright © 2011-2022 走看看