泛型委托使用_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 泛型委托使用

泛型委托使用

 2016/5/23 5:31:23  tuohaibei  程序员俱乐部  我要评论(0)
  • 摘要:泛型委托基础classProgramclassProgram{//泛型委托,与普通委托类似,不同之处只在于使用泛型委托要指定泛型参数publicdelegateTMyGenericDelegate<T>(Tobj1,Tobj2);intAddInt(intx,inty){returnx+y;}stringAddString(strings1,strings2){returns1+s2;}staticvoidMain(string[]args){Programp=newProgram
  • 标签:使用 泛型

泛型委托基础

 

class Program  

class Program  
{  
        // 泛型委托,与普通委托类似,不同之处只在于使用泛型委托要指定泛型参数          
        public delegate T MyGenericDelegate<T>(T obj1,T obj2);  
  
        int AddInt(int x, int y)  
        {  
            return x + y;  
        }  
  
        string AddString(string s1, string s2)  
        {  
            return s1 + s2;  
        }  
         
        static void Main(string[] args)  
        {  
            Program p = new Program();  
             
            MyGenericDelegate<int> intDel;  
            intDel = p.AddInt;  
            Console.WriteLine("int代理的值是{0}", intDel(100, 200));  
  
            MyGenericDelegate<string> stringDel;  
            stringDel = p.AddString;  
            Console.WriteLine("string代理的值是{0}", stringDel("aaa", "bbb"));  
        }  
}  

 

为了方便开发,.NET基类库针对在实际开发中最常用的情形提供了几个预定义好的委托,这些预定义委托用得很广,比如在编写lambda表达式和开发并行计算程序时经常要用到他们

     .NET提供的泛型委托包括action和func

     感悟:对泛型委托基本属于有点认识,但从来没真正在项目中使用过,有时感觉没有合适的场景应用,但看了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()); 

--此文章根据网络资源整理.纯属个人笔记,别无其它商业用途.

发表评论
用户名: 匿名