• 委托和事件


    委托

    1. 委托的作用:

      1. 对签名相同的不同函数进行抽象,对它们进行封装从而达到代码复用的目的
      2. 异步调用和回调
    2. 如何使用,正常的使用可以分为三步:

      1. 定义委托 delegate int GetLengthDel(string input)

      2. 创建委托的实例并指向合适的方法 GetLengthDel del=GetLengthMethod 等于
        GetLengthDel del =new GetLengthDel(GetLengthMethod);

      3. 同步或者异步调用方法

        del.Invoke("input string");//
        del("input string");//和上面一行是等效的 ,而且都是同步调用
        //异步调用,事实上netcore已经禁止直接写这样的异步调用了;所以对这种过时的也不再讲解了
        //del.BeginInvoke
        
    3. 继承体系: 自定义委托-->System.MulticastDelegate-->System.Delegate
      System.MulticastDelegate 重要的内部成员包括

      1. _invocationList
        MulticastDelegate 定义了 私有的_invocationList字段,内容是 System.Delegate数组。
        可以通过 GetInvocationList公共方法获取到里面的内容; 而设置 _invocationList里的内容是通过 +=(调用 Delegate.Combine ) , -+ (调用 Delegate.Remove)来进行的.
      2. _target 从 基类 System.Delegate 继承而来。 当委托上绑定的是实例方法时,保存方法所在的实例对象的地址;当是静态方法时,值为null 。
      3. _methodPtr 从 基类 System.Delegate 继承而来。 保存绑定的方法内存地址 。
    4. 关于委托链条

      如果一个委托是绑定了多个方法(多播委托),并且这些方法是有返回值的,当执行完多个方法后,返回值是最后一个方法的返回值,而不是多个方法累计的值或者其他值。如果中间一个方法出现错误,绑定的后续方法将不会执行。
      想要实现累计值,可以通过GetInvocationList方法获取委托列表,循环调用,并自己维护累计值。
      另外注意: ① 如果委托绑定的方法大于1个, _invocationList才不等于 null; ② 委托内的_target_methodPtr总是等于_invocationList数组中的最后一个元素(System.Delegate对象)的_target_methodPtr

    事件

    1. 事件是对委托的进一步封装,外部只能访问 += , -= ,
      类似属性提供的 Get , Set访问器 ,它提供的是 Add_xxx , Remove_xxx 对他可访问的委托进行维护 (其实也是调用 Delegate.CombineDelegate.Remove,) xxx一般为对应的委托名称。
    2. 作用:想比对外提供委托,增强了安全性和减少了不规范操作的带来的脆弱性。
    3. 使用:
      1.完全自定义
          //定义委托
          public delegate void MyClientEventHandler(string p);
          //定义事件
          public static event MyClientEventHandler MyClientEvent; 
          //绑定方法 省略见下面的例子
          //触发事件 省略见下面的例子
      
      1. 借助系统提供的 EventHandler
      #region 非泛型
          // 定义非泛型事件
          public event EventHandler MyEvent;
          //绑定方法
          MyEvent+=NewCarIsHere;
          //触发事件 
          MyEvent?.Invoke(this,new System.EventArgs());
          //绑定到事件的方法
          public void NewCarIsHere(object sender, CarInfoEventArgs e) =>
              Console.WriteLine($" MyEvent happened ");
      #endregion 
      
      #region 泛型事件 
          // 定义泛型事件
          public event EventHandler<CarInfoEventArgs> CarArrivaledEvent;
      
          //定义泛型参数
          public class CarInfoEventArgs : EventArgs
          {
              public CarInfoEventArgs(string car) => Car = car;
              public string Car { get; }
          }
          //绑定方法
          CarArrivaledEvent+=CarArrivaled;
          //触发事件
          CarArrivaledEvent?.Invoke(this, new CarInfoEventArgs(car));
      
          //绑定到事件的方法
          public void CarArrivaled(object sender, CarInfoEventArgs e) =>
              Console.WriteLine($"  {e.Car}  Arrivaled ");
      #endregion
      
      
  • 相关阅读:
    session中删除数组中的某一个值
    Windows 查看端口占用进程并关闭
    Debian 9 / Debian 10 / Ubuntu 18.04 / Ubuntu 18.10快速开启BBR加速 或 关闭BBR加速
    在ASP.NET Web API 2中使用Owin OAuth 刷新令牌(示例代码)
    在ASP.NET Web API 2中使用Owin基于Token令牌的身份验证
    Web API 2 的操作结果
    WebApi接口安全性 接口权限调用、参数防篡改防止恶意调用
    关于EF中使用Migrations的一些小提示
    Entity Framework 6 多对多增改操作指南
    用MVC5+EF6+WebApi 做一个考试功能(六) 仓储模式 打造EF通用仓储类
  • 原文地址:https://www.cnblogs.com/francisXu/p/13647913.html
Copyright © 2020-2023  润新知