• 委托及事件隐藏的信息


    委托,是一种特殊的类,它是将调用时操作对象和指定方法的封装。委托的构造函数,需两个参数target,methodPtr分别用于指定操作的对象和方法。委托的调用通过Invoke方法,方法的原型及委托定义一致。委托同时提供了BeginInvoke及EndInvoke方法用于支持异步。

    委托链的形成利用Delegate的基类MulticastDelegate的_prev字段,[关于Delegate与MultiCastDelegate],使用Combine和Remove方法操作委托链。

    防止委托链中的由于单个委托出现异常或占阻塞,可利用MulticastDelegate的GetInvocationList()获取委托链中委托克隆体形成委托数组,用于实现对其的更多控制。

    如果在不明确委托对应方法原型的时候使用委托。需要用到Delegate.CreateDelegate方法。

       public class Delegate
    {
    public static Delegate CreateDelegate(Type delType, System.Reflection.MemberInfo mi);
    public static Delegate CreateDelegate(Type delType, Type type, string methodName);
    public static Delegate CreateDelegate(Type delegateType, object obj, String methodName);
    public static Delegate CreateDelegate(Type delegateType, object obj, string methodName, Boolean ignoreCase);
    //......
    public object DynamicInvoke(object[] args);
    }

    Demo:(通过指定生成委托对象的参数实现在未知方法原型时的调用)

    namespace DelegateDemo
    {
    delegate object TwoInt32(int n1, int n2);
    delegate object OneString(string s1);
    class Program
    {
    static void Main(string[] args)
    {
    Delegate d = Delegate.CreateDelegate(typeof(TwoInt32), typeof(Program), "Add");
    object result = d.DynamicInvoke(1, 2);
    Console.WriteLine(result);
    d = Delegate.CreateDelegate(typeof(OneString), typeof(Program), "NumChars");
    result = d.DynamicInvoke("hello cnblogs!");
    Console.WriteLine(result);
    }
    static object Add(int n1, int n2)
    {
    return n1 + n2;
    }
    static object NumChars(string s1)
    {
    return s1.Length;
    }
    }

    事件的定义:
    public event EventHandler MyEvent;

    事件的作用是通知侦听事件的用户执行其自定义的操作。关于事件的侦听与注销,实则是对委托链的操作,编译器会将事件转化成一个委托字段及两个方法(add_*,remove_*用于操作委托字段)。 事件,我理解的是将有效信息包装到继承到EventArgs对象中,触发事件,通知事件侦听者作其定义的反应。事件的必须具备的三个能力:对象登记事件;对象注销事件;定义事件的对象维护登记对象的集合并通知。这三项功能从实现角度看,委托链都能做到,而事件是对委托链做了一层包装。博客园中有博友曾提过“事件与委托的关系好比字段与属性的关系。”这可以从显式控制事件注册的实现中看到:

    显式控制事件注册:

    public  delegate void SampleEventHandler(object sender,EventArgs args);
    private SampleEventHandler sampleEventHandlerDelegate;
    public  SampleEventHandler Sample
    {
    add
    {
    sampleEventHandlerDelegate = (SampleEventHandler)Delegate.Combine(sampleEventHandlerDelegate,value);
    }
    remove
    {
    sampleEventHandlerDelegate=(SampleEventHandler)Delegate.Remove(sampleEventHandlerDelegate,value);
    }
    }

    从显式控制事件注册的代码可以很清晰的看出,是通过声明一个委托字段,然后定义其访问器来实现的。FCL中System.Windows.Forms.Control一个类中定义了近60个事件,也是通过这种方式实现用于减少内存的浪费。基本思想:让每个对象保存一个事件/委托对的集合,当新对象被构建时,集合为空;当事件被登记时,如果集合中存在,则将委托实例给合到委托链上;若不存在,则将新事件及实例添加到集合。

  • 相关阅读:
    普里姆算法和克鲁斯卡尔算法
    Windows 杀死8080端口进程
    电脑的ipv4地址每次重启后自动还原
    java常用的设计模式有哪些
    》》》ORA12516 "TNS监听程序找不到符合协议堆栈要求的可用处理程序" 解决方案
    Oracle 11g服务器安装详细步骤——图文教程
    IDEA修改选中行背景色 mac电脑 2022年7月
    java字符串固定长度,左补空格,或右补空格
    kubectl命令使用
    k8s 之 TLS Bootstrapping
  • 原文地址:https://www.cnblogs.com/spirit/p/1566598.html
Copyright © 2020-2023  润新知