日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Emit学习-进阶篇-定义事件

發布時間:2024/4/17 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Emit学习-进阶篇-定义事件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Emit學習-進階篇-定義事件

之前在研究如何用Emit為動態類添加事件,本來以為會非常簡單,但是卻碰到了許多的問題,有些問題在之前的答疑篇中已經提到了,并予以了解決,雖然有些地方自己也不是很明白,但畢竟還是解決了,最后比較我寫的IL代碼,和系統自動生成的,總有一些地方無法做到一致。特別是在為事件添加add和remove方法時,碰到了許多問題,下面我將針對這些問題進行講解。按照慣例,先給出要實現的類的C#代碼,方便反編譯后對照著進行IL代碼的書寫,代碼如下:

public class Publisher {private bool isStart = false;private Random random = new Random(DateTime.Now.Millisecond);public void Start(){if (!isStart){isStart = true;GenerateRand();}}public void Stop(){isStart = false;}private void GenerateRand(){while (isStart){OnRandGenerated(random.Next(10000));Thread.Sleep(1000);}}#region Eventpublic event EventHandler<RandGeneratedEventArgs> RandGenerated;protected virtual void OnRandGenerated(int rand){RaiseRandGeneratedEvent(rand);}private void RaiseRandGeneratedEvent(int rand){EventHandler<RandGeneratedEventArgs> temp = RandGenerated;if (temp != null){RandGeneratedEventArgs arg = new RandGeneratedEventArgs(rand);temp(this, arg);}}#endregion }

?

  首先,我們定義類中的相關字段及方法,這部分使用之前基礎篇中提到過的步驟就可以完成,不再累述,但是要指出的一點是,在類中,以如下形式初始化的字段:private Random random = new Random(DateTime.Now.Millisecond);如果初始化的值不是常量,則需要在無參構造函數中對齊進行初始化,否則可以使用FieldBuilder的SetConstant方法進行初始化。

  在定義事件時,發現需要手動添加事件的add和remove方法,在這里面會用到事件的本身,而OpCodes指令中好像也沒有加載事件的指令,只有加載字段的指令,然后仔細研究了自動生成的IL代碼,發現其中生成了一個與定義的事件的同名的私有字段,然后相關的訪問都是通過對這個字段的訪問來進行的,于是豁然開朗,看來Reflector果然是個好東西呀!

  當定義事件的add和remove方法時,需要注意,我們平時在C#中使用的都是形如+=、-=這樣的形式,但是我用這種方法后發現行不通,最后又是在Reflector的幫助下,發現應該分別使用Delegate的Combine和Remove方法,廢話不多說,代碼和相關注釋如下:

//定義事件,事件的可訪問性由和它相關的getset方法決定 EventBuilder randGeneratedEvent = publisherTypeBuilder.DefineEvent("RandGenerated", EventAttributes.None, eventType);MethodBuilder addEventBuilder = publisherTypeBuilder.DefineMethod("add_RandGenerated", MethodAttributes.Public, null, new Type[] { eventType }); //注意在我們使用事件時,使用的是+=操作,但在IL代碼中并不是如此,應該使用Delegate.Combine方法 ILGenerator addEventIL = addEventBuilder.GetILGenerator();addEventIL.Emit(OpCodes.Ldarg_0); addEventIL.Emit(OpCodes.Ldarg_0); addEventIL.Emit(OpCodes.Ldfld, randGeneratedField); addEventIL.Emit(OpCodes.Ldarg_1); addEventIL.Emit(OpCodes.Call, typeof(Delegate).GetMethod("Combine", new Type[] { eventType, eventType })); //返回的是Delegate類型,所以需要進行轉換 addEventIL.Emit(OpCodes.Castclass, eventType); addEventIL.Emit(OpCodes.Stfld, randGeneratedField);randGeneratedEvent.SetAddOnMethod(addEventBuilder);MethodBuilder removeEventBuilder = publisherTypeBuilder.DefineMethod("remove_RandGenerated", MethodAttributes.Public, null, new Type[] { eventType }); //注意在我們使用事件時,使用的是-=操作,但在IL代碼中并不是如此,應該使用Delegate.Remove方法 ILGenerator removeEventIL = removeEventBuilder.GetILGenerator();removeEventIL.Emit(OpCodes.Ldarg_0); removeEventIL.Emit(OpCodes.Ldarg_0); removeEventIL.Emit(OpCodes.Ldfld, randGeneratedField); removeEventIL.Emit(OpCodes.Ldarg_1); removeEventIL.Emit(OpCodes.Call, typeof(Delegate).GetMethod("Remove", new Type[] { eventType, eventType })); //返回的是Delegate類型,所以需要進行轉換 removeEventIL.Emit(OpCodes.Castclass, eventType); removeEventIL.Emit(OpCodes.Stfld, randGeneratedField);randGeneratedEvent.SetRemoveOnMethod(removeEventBuilder); posted on 2011-03-28 21:40 林冠逹 閱讀(...) 評論(...) 編輯 收藏

轉載于:https://www.cnblogs.com/viclgd/archive/2011/03/28/1998138.html

總結

以上是生活随笔為你收集整理的Emit学习-进阶篇-定义事件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。