委托事件小计

委托提供了安全的方法回调机制。
常见用法:

1.winform asp.net 中的按钮事件。
2.winform中 窗体A弹出窗体B, 点击窗体B的按钮,修改窗体A的属性。
3.封装流程,通过委托注入,实现了更加轻量级的 模板方法模式的实现。

首先我们定义一个委托

public delegate void MyDelegate(string name);

事实上,编译器会将该委托编译为一个类

    public sealed class MyDelegate : MulticastDelegate
    {
        public MyDelegate(object @object, IntPtr method);
        public virtual IAsyncResult BeginInvoke(string name, AsyncCallback callback, object @object);
        public virtual void EndInvoke(IAsyncResult result);
        public virtual void Invoke(string name);
    }

该类 主要包含了 一个构造函数,一个invoke方法,以及一对异步invoke方法。

委托类的 继承层次 为 MyDelegate -> MulticastDelegate -> Delegate

Delegate中有两个重要的属性 Method 和 Target 

        // 摘要:
        //     获取委托所表示的方法。
        //
        // 返回结果:
        //     描述委托所表示的方法的 System.Reflection.MethodInfo。
        //
        // 异常:
        //   System.MemberAccessException:
        //     调用方不能访问委托所表示的方法(例如,当该方法为私有时)。
        public MethodInfo Method { get; }
        //
        // 摘要:
        //     获取类实例,当前委托将对其调用实例方法。
        //
        // 返回结果:
        //     如果委托表示实例方法,则为当前委托对其调用实例方法的对象;如果委托表示静态方法,则为 null。
        public object Target { get; }

Delegate还定义了一系列的 静态方法。

委托的写法有以下四种:

        
        void GetName(string name) { }
        MyDelegate myDelegate = new MyDelegate(this.GetName);
        MyDelegate myDelegate2 = this.GetName;
        MyDelegate myDelegate3 = delegate(string a) { this.GetName(a); };
        MyDelegate myDelegate4 = a => this.GetName(a);

.net中的委托是多播委托,可以将多个委托绑定到一个委托链上,同理也可以删除委托。

            myDelegate += this.GetName;
            myDelegate += myDelegate2;
            myDelegate -= myDelegate3;

可以通过 MulticastDelegate 获取到委托链上的所有委托

        //
        // 摘要:
        //     按照调用顺序返回此多路广播委托的调用列表。
        //
        // 返回结果:
        //     一个委托数组,这些委托的调用列表合起来与此实例的调用列表一致。
        //
        // 异常:
        //   System.MemberAccessException:
        //     无法创建抽象类的实例,或者用后期绑定机制调用了该成员。
        public override sealed Delegate[] GetInvocationList();

该函数返回的是 Delegate[] ,实际使用时需要强制转换为对应的委托类型。

委托的调用方法
可以将一个委托变量当做方法直接调用

            myDelegate("YLWS");
           //实际上会调用委托上的Invoke方法
            myDelegate.Invoke("YLWS");

同时,委托提供了一组异步调用的方法

            myDelegate.BeginInvoke("YLWS",
                a =>
                {
                    Thread.Sleep(5000);
                    AsyncResult result = (AsyncResult)a;
                    MyDelegate del = (MyDelegate)result.AsyncDelegate;
                    del.EndInvoke(a);
                    string data = a.AsyncState.ToString();//获取到 @objec对象
                    //dosomething
                },
                "Test"
                );

事件是对委托的封装,对外只提供了 += 和-= 两种操作。最简单的对应就是 属性之于字段。
属性风格的事件如下:

        public delegate void MyDelegate(string name);
        private MyDelegate nameChanged;
        public event MyDelegate OnNameChanged
        {
            add
            {
                nameChanged += value;

            }
            remove
            {
                nameChanged -= value;
            }
        }

参考 委托和事件 从.NET中委托写法的演变谈开去 

扩展 谈谈.NET中常见的内存泄露问题——GC、委托事件和弱引用

posted @ 2013-07-19 10:58  YLWS  阅读(284)  评论(0编辑  收藏  举报