泛型委托使用

泛型委托基础

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()); 

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

时间: 2024-11-09 06:40:56

泛型委托使用的相关文章

c#系统泛型委托

Action<T> 无返回值的系统泛型委托 namespace ConsoleApp1 { public class UserInfo { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } } class Program { private static List<UserInfo> getInit() { return new List<User

泛型委托当参数传递

假如有一个Person类: public class Person { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public string Title { get; set; } } 执行一个方法: /// <summary> /// 传递一个泛型委托方法 /// </summary> /// <param name="acti

泛型委托

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 泛型委托 { public delegate int DelCompare<T>(T t1, T t2); // public delegate int DelCompare(object o1, object o2); class Progra

关于学习C#泛型委托过程中发现的一些疑惑,大家一起讨论下

大家知道泛型委托Action,是定义一个没有返回值的委托. 例如: public Action<int, int> AddAction = (x, y) => { Console.WriteLine(x+y); }; 定义一个Action 可以在Action上F12进入可以看到源码为: public delegate void Action<T1, T2>(T1 arg1, T2 arg2); 这里发现一个问题,T1,T2是什么类型呢,在哪里定义的,我按F12并没有找到对应的

委托学习笔记后续:泛型委托及委托中所涉及到匿名方法、Lambda表达式

引言: 最初学习c#时,感觉委托.事件这块很难,其中在学习的过程中还写了一篇学习笔记:委托.事件学习笔记.今天重新温故委托.事件,并且把最近学习到和委托相关的匿名方法.Lambda表达式及泛型委托记录下来,以备复习使用. 委托: 日常工作中,常常见到委托用在具体的项目中.而且委托使用起来相对来说也是非常简单的,下面列举一个委托实例用以说明如何使用委托,代码如下: class Program { public delegate int CalculateDelegate(int x, int y)

C#语法糖之第六篇: 泛型委托- Predicate&lt;T&gt;、Func&lt;T&gt;

今天继续分享泛型委托的Predicate<T>,上篇文章讲了Action委托,这个比Action委托功不一样的地方就是委托引用方法是Bool返回值的方法,Action为无返回值.首先我们看一下它的定义吧: 1 public delegate bool Predicate<T>(T obj); 从其定义可以看到,此委托引用一个返回bool 值的方法,在实际开发中,通常使用Predicate<T>委托变量引用一个“判断条件函数”,在判断条件函数内部书写代码表明函数参数所引用

泛型委托学习进程

首先先回顾委托的使用过程步骤: 委托使用总结: (1)     委托声明(定义一个函数原型:返回值+参数类型和个数)注:在类的外部--中介(房产中介商) (2)     根据委托定义"具体"的方法------房源   注:在类中定义方法 (3)     创建委托对象,关联"具体方法"---中介商拥有房源  注意:在主函数中操作 第一种方式:使用new初始化.第二种方式:直接给委托变量赋值方法 (4)     通过委托去调用方法(而不是直接调用方法)------中介带

c#中的泛型委托(@WhiteTaken)

今天学习一下c#中的泛型委托. 1.一般的委托,delegate,可以又传入参数(<=32),声明的方法为  public delegate void SomethingDelegate(int a); 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace delegate

C#中使用委托、接口、匿名方法、泛型委托实现加减乘除算法

使用C#实现加减乘除算法经常被用作新手练习.本篇来分别体验通过委托.接口.匿名方法.泛型委托来实现. 使用委托实现 加减乘除拥有相同的参数个数.类型和返回类型,首先想到了使用委托实现. //创建一个委托 public delegate decimal MathOperation(decimal left, decimal right); //创建方法参数和返回结果符合委托的定义 public static decimal Add(decimal left, decimal right) { re

List&lt;string&gt;中的泛型委托

我们先看List<T>.Sort().其定义是:public void Sort( Comparison<T> comparison ) 其要求传入的参数是Comparison<T> comparison.那我们看看Comparison<T> comparison 要求我们传入哪些参数.返回什么样的值. 查阅MSDN后,我们发现Comparison<T> 要求我们传入两个T的示例,即t1和t2:返回结果是整数,如果t1<t2返回-1,如果相