委托事件小计
委托提供了安全的方法回调机制。
常见用法:
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; } }