现在的位置: 首页 > 综合 > 正文

还是委托的解释,感觉作者理解的也很好,就转过来了

2012年12月06日 ⁄ 综合 ⁄ 共 2984字 ⁄ 字号 评论关闭
关于委托的使用最好是通过实例,掌握了某种模式之后就会逐渐理解其工作的原理了。下面我写一段简单的通过定义事件的代码:(建议将代码拷贝到VS2005中再看会更清晰一点)

/// <summary>
/// 声明一个TextChanged委托,该委托有一个TextChangedEventArgs类型的参数作为数据的传递。
/// </summary>
/// <param name="e"></param>
public delegate void TextChangedHandler(TextChangedEventArgs e);

public partial class Form1 : Form
{
/// <summary>
/// 定义一个TextChanged类型的事件。
/// </summary>
public event TextChangedHandler TextChanged;

private string m_Text;
/// <summary>
/// Text属性
/// </summary>
public string Text
{
get { return m_Text; }
set
{
m_Text = value;
// 当前类的m_Text被修改的时候发布TextChanged事件。
OnTextChanged(m_Text);
}
}
/// <summary>
/// 发布TextChanged事件。
/// </summary>
/// <param name="text"></param>
private void OnTextChanged(string text)
{
if (TextChanged != null)
{
TextChanged(new TextChangedEventArgs(text));
}
}

public Form1()
{
InitializeComponent();
this.TextChanged += new TextChanged(Form1_TextChanged);
}
/// <summary>
/// 当发生了TextChanged事件之后的处理方法。
/// </summary>
/// <param name="e"></param>
void Form1_TextChanged(TextChangedEventArgs e)
{
MessageBox.Show(e.Text);
}
}

public class TextChangedEventArgs:EventArgs
{
private string m_Text;
public string Text
{
get{return m_Text;}
}

public TextChangedEventArgs(string text)
{
m_Text = text ;
}
}
上面的这个类是一个简单的WinForm下的Form窗口对象。在该类前面声明了一个TextChanged委托。其实委托就是一个回调函数的格式定义。下面我来解释一下上面这段代码的工作方式。

上面这段代码是微软程序种最标准的事件声明和发布的方式。在所有微软的控件中到处充斥这这种代码,如果你可以反编译微软的代码的话,你会看到非常非常多的On.....方法,这种以On开头的方法都是发布事件以及内部事件处理的方法。

那么怎样声明一个事件呢?这要看你要用这个事件做什么了,通常情况下我们使用事件发布我们当前对象的某个状态被改变了,已通知那些对这个状态感兴趣的对象。如果没有什么需要传递的信息,那么这种事件可以直接才采用微软提供的最简单的委托来声明这个事件——EventHandler.一般情况下微软的委托都是以Handler为后缀的,用来区分方法名所用,而且也可以生动的告诉使用者一个委托就是一个句柄一个指针并非一个实体。上面的代码中“public event TextChangedHandler TextChanged;”就是用我们自己定义的TextChangedHandler委托声明的事件。

那么这个事件怎么使用呢?我们声明了不去用那么也是白费。我们的目的是在Form1的Text属性被更改的时候,即时的通知某些关心这个属性的对象,因此我们就要在Form1的Text的属性的Set方法中写下一个
set
{
m_Text = value;
// 当前类的m_Text被修改的时候发布TextChanged事件。
OnTextChanged(m_Text);
}
当程序通过Text的Set方法为Text赋值之后,就会调用一个OnTextChanged()方法,并通过参数形式将改变之后的Text值传递给这个方法。而这个OnTextChanged方法就会检测当前对象的TextChanged事件是否有被注册的。if (TextChanged != null),这个判断就是判断是否有对象注册了这个事件。注:当有对象通过+=的形式注册了事件则事件TextChanged就不等于空了。上利中this.TextChanged += new TextChanged(Form1_TextChanged)已经注册了这个事件,因此在OnTextChanged方法中的判断是成立的,所以代码TextChanged(new TextChangedEventArgs(text));将会被调用。这里看起来好像很奇怪,怎么TextChanged事件变成了一个方法,别忘了我们是用TextChangedHandler这个代理声明的这个事件,因此这个事件的形式就会和TextChangedHandler的格式一样。

在这里TextChanged(new TextChangedEventArgs(text));做的事情类似于一个循环,他会找到所有已经注册这个事件的方法,也就是上例中
/// <summary>
/// 当发生了TextChanged事件之后的处理方法。
/// </summary>
/// <param name="e"></param>
void Form1_TextChanged(TextChangedEventArgs e)
{
MessageBox.Show(e.Text);
}
只要注册了这个事件并具有这种方法的对象,都将被调用。这也也就是为什么将委托叫回调函数的原因。这样每个关注Form1.Text属性的对象都可以有自己的处理方式,待发生了这个事件之后,有事件发布程序去调用这些已经定义好的操作。这样就充分达到低耦合度的目的。

至于上例中所定义public class TextChangedEventArgs:EventArgs
类,直接继承自系统的EventArgs类,作用于系统的EventArgs类一样都只是在事件发生的时候用来传递事件数据的用的。当然这只是微软内部关于事件数据的一种约定,我们在代理中也可以传递其他形式的类的对象,不过应尽量使用微软的这种形式来传递事件数据,这样也有利于改善程序的可读性。我们可以利用这种形式定义一些更加复杂的数据在事件发生时进行传递。这样就可以更加灵活的使用事件来进行对象之间的交流了。

上面的解释是我个人对委托的理解,如有不正确的地方还请高手指正。对于提问者我想我这种事件的处理方式对于你来说已经非常合适,因为我在开发过程中经常用这种模式来定义事件,这样我的程序灵活性加大了很多,而且这也是微软奉行的模式,总会有他的道理的。希望对你有所帮助。(以上例子以及说明完全由我个人所写没有拷贝任何参考资料)

抱歉!评论已关闭.