上次把一个类的构造函数、字段、属性的写法搞定了,这次轮到事件,讲事件当然就不能不提委托,当然方法也是不少了的(类方法嘛倒是从一开始就在用了,Main()也是类里的方法)。
既然要写一个完整点的东西喽,那就索性再声明一个自己的EventArgs类,这个类基本上什么事没有,只有一个属性返回当前的时间。
public class myEventArgs : EventArgs {
public myEventArgs() {
}
public DateTime Dt {
get {
return DateTime.Now;
}
}
}
给一下CodeDOM代码,顺便复习一下前面的:
CodeTypeDeclaration EventArgsClass = new CodeTypeDeclaration("myEventArgs");
EventArgsClass.BaseTypes.Add("EventArgs");
//构造函数
CodeConstructor mEAcreate = new CodeConstructor();
mEAcreate.Attributes = MemberAttributes.Public;
EventArgsClass.Members.Add(mEAcreate);
//属性Dt
CodeMemberProperty Dt = new CodeMemberProperty();
Dt.Name = "Dt";
Dt.Type = new CodeTypeReference("DateTime");
Dt.Attributes = MemberAttributes.Public | MemberAttributes.Final;
Dt.GetStatements.Add(new CodeMethodReturnStatement(new CodePropertyReferenceExpression(new
CodeTypeReferenceExpression("DateTime"),"Now")));
EventArgsClass.Members.Add(Dt);
sample.Types.Add(EventArgsClass);//加到Namespace里
声明委托一句:public delegate void myEventHandler(object sender, myEventArgs e);要用到一个新的CodeDOM类了。上次讲类层次结构的时候没讲到,声明委托用的CodeTypeDelegate是从CodeTypeDeclaration继承下来的,它只是比CodeTypeDeclaration多了两个属性,一个是设置委托的参数:Parameters,一个设置委托的返回类型的ReturnType。
上面的委托没有返回值,至于参数Parameters的用法,与方法里的参数设置是一致的,参数声明就用CodeParameterDeclarationExpression(好象在(三)提到过)。
上面的篇幅是横插进来的,下面回到(四)的那个DemoClass类里,声明一下事件,这倒是很简单。
CodeMemberEvent MyEvent = new CodeMemberEvent();
MyEvent.Name = "MyEvent";
MyEvent.Attributes = MemberAttributes.Public;
MyEvent.Type = new CodeTypeReference("myEventHandler");
MyClass.Members.Add(MyEvent);
一眼就能看出来,事件名是“MyEvent”,类型是上面声明过的那个“myEventHandler”
在一个保护方法里引发事件MyEvent:
// 事件方法
protected virtual void OnMyEvent(myEventArgs e) {
if ((this.MyEvent != null)) {
Console.WriteLine("Invokes MyEvent");
this.MyEvent(this, e);
}
}
随随便便在类里弄个方法写写简单的语句在(三)里就已经熟透了,不过这里曾经大意过一下。this.MyEvent(this, e);这句如果排除上下文及不要去望文生义的话是不是就是一个方法调用啦,第一次写的时候就把它当成方法调用写的,因为方法调用表达CodeMethodInvokeExpression用得是很熟,看到这个形式代码当时想也不想就写成方法调用了。居然编译通过,运行也通过,后来试了一下其实连上面那个this.MyEvent != null 里的“this.Myevent”都可以用CodeFieldReferenceExpression来代替CodeEventReferenceExpression的,出来的代码效果是一样的,但这种写法是概念不清的表现啦,还是改过来。用CodeDelegateInvokeExpression来写this.MyEvent(this, e);这一句:
CodeDelegateInvokeExpression(new CodeEventReferenceExpression(new CodeThisReferenceExpression(),"MyEvent"),new CodeExpression[] {new CodeThisReferenceExpression(),new CodeArgumentReferenceExpression("e")})
到时为了看一下附加委托与移除委托的效果,把OnMyEvent再放到一个public的Method里
public void MyMethod() {
Console.WriteLine("DemoClass.MyMethod");
this.OnMyEvent(new myEventArgs());
}
这里this.OnMyEvent(new myEventArgs());是的的确确的方法调用了,要用CodeMethodInvokeExpression来做了,不要混了,这个方法里没有什么新东西,就不详述了。(其实还是有的,new myEventArgs()这个就是新东西,不过创建新对象的功能放下次了)
至此事件的功能结束,一个比较完整的类也算完成,当然还有一些功能没有,比如析构函数如何写之类,现在还没找到方法(到时要把CodeDOM中碰到的困惑一起列一下)。
写好东西总是要测试一下的,测试代码也让CodeDOM来生成算了,下次再生成一个测试这个DemoClass的类的代码,主要讲一下对象创建,数组索引(我们上面声明过一个索引器属性的,要用上),及附加、移除委托(让事件发挥作用啦)。