Phoenix's Blog
博客园
首页
新随笔
联系
订阅
管理
25 Posts :: 3 Stories :: 25 Comments :: 0 Trackbacks
公告
与我联系
发短消息
搜索
常用链接
我的随笔
我的空间
我的短信
我的评论
更多链接
我的参与
我的新闻
最新评论
我的标签
留言簿
(1)
给我留言
查看留言
随笔分类
.Net(4)
ASM & CPP
Database(2)
Regular Expressions(1)
随笔档案
2008年8月 (1)
2007年12月 (1)
2007年4月 (1)
2007年2月 (2)
2006年11月 (1)
2006年8月 (1)
2006年6月 (1)
2006年2月 (2)
2005年12月 (1)
2005年7月 (1)
2005年1月 (1)
2004年12月 (3)
2004年11月 (3)
2004年10月 (6)
文章分类
.Net Framework(2)
Asp.Net
C#
OLAP(1)
Regular Expressions
SQL Server
XML & XSLT
文章档案
2005年5月 (1)
2005年2月 (2)
相册
生活
Friends
Laser.Net
纯爷们
最新评论
阅读排行榜
1. Oracle Listener报“TNSLSNR.exe 应用程序错误”(1562)
2. 如何在外部得到一个event是否已被注册(1491)
3. SQL2000自动备份数据库到远程机器(872)
4. 正则表达式超时(835)
5. Windows下安装SQLPlus的帮助(637)
评论排行榜
1. 如何在外部得到一个event是否已被注册(9)
2. 正则表达式超时(8)
3. FlashGet的堕落(5)
4. 求救手工设置笔记本IRQ的方法(3)
5. Windows下安装SQLPlus的帮助(0)
如何在外部得到一个event是否已被注册
同事有个这样的需求:需要判断一个对象的event是否已经被注册过了,如果没有,则注册一个事件来执行默认操作。
比方说类ClassA
public
class
ClassA
{
public
event
EventHandler Event1;
public
EventHandler Delegate1;
private
string
id;
protected
virtual
void
OnEvent()
{
if
(
this
.Event1
!=
null
)
{
this
.Event1(
this
, EventArgs.Empty);
}
}
public
ClassA()
{
this
.Delegate1
=
delegate
(
object
sender, EventArgs e)
{
Console.WriteLine(
"
Delegate
"
);
}
;
}
public
void
Test()
{
OnEvent();
}
}
现在在代码中已经得到一个ClassA的实例,但是如果得到其Event1的情况呢,我们首先想到了使用Reflection, 查到在Reflection中有个EventInfo类型
ClassA a
=
new
ClassA();
EventInfo ei
=
typeof
(ClassA).GetEvent(
"
Event1
"
);
可是这个EventInfo只能通过
void
AddEventHandler
(
object
target,
Delegate
handler);
void
RemoveEventHandler
(
object
target,
Delegate
handler);
这两个方法对已知的target进行事件的Hook up (
http://msdn2.microsoft.com/zh-cn/library/ms228976.aspx
),无法使用如PropertyInfo, FieldInfo之类的GetValue方法得到一个MulticastDelegate实例。
后来想想,事件的声明和公有Field的声明一样,唯独多了一个event关键字,但是采用这种方式还是不能得到一个FieldInfo
FieldInfo fi
=
typeof
(ClassA).GetField(
"
Event1
"
, BindingFlags.Public
|
BindingFlags.Instance);
不甘心之余用ildasm查看了一下,终于发现一个简单的event声明,编译器实际上处理了如下操作:
private
event
EventHandler Event1;
public
void
add_Event1(EventHandler value)
{
//
Do addition.
}
public
void
remove_Event1(EventHandler value)
{
//
Do removal.
}
所以实际上我们必须是得到一个私有的Field Event1,于是将代码改了改
FieldInfo fi
=
typeof
(ClassA).GetField(
"
Event1
"
, BindingFlags.NonPublic
|
BindingFlags.Instance);
呵呵,终于能够得到一个FieldInfo的实例了,接下来使用FieldInfo.GetValue方法得到一个MulticastDelegate (未注册事件时为null). 这样我们可以对这个MulticastDelegate对象进行操作,实现真正的事件Hook up.
奇怪的是类似的代码在同事那边执行不过,用反编译工具查看了一下,发现其事件是采用自定义的方式
public
event
EventHandler Event2
{
add
{
}
remove
{
}
}
真正的事件delegate是存放在一个EventHandlerList中 (请参阅MSDN: .Net Framework Developer's Guide: Handle multiple events using event properties.)
所以接下来的就是找到这个EventHandlerList和MulticastDelegate的key,然后取得这个MulticastDelegate.
使用EventHandlerList易于管理,例如在Dispose资源时,统一Fire事件时等等,但是EventHandlerList本身是线性列表的对象,当这个List里面的delegate变得非常多时,查询的效率会变得非常差. :)
posted on 2007-12-26 15:01
Phoenix
阅读(1491)
评论(9)
编辑
收藏
网摘
所属分类:
.Net
评论
#1楼
2007-12-26 15:10
A.Z! [未注册用户]
当这个List里面的delegate变得非常多时,查询的效率会变得非常差. :)
一个对象event再多也不会超过100个
回复
引用
#2楼
2007-12-26 15:12
留恋星空
有什么作用?
回复
引用
查看
#3楼
2007-12-26 16:25
overred
Activator.CreateInstance
回复
引用
查看
#4楼
2007-12-26 17:35
装配脑袋
add和remove是Event唯一暴露的功能,其他做法都是不可靠的,在特定对象模型上的行为无法预测
回复
引用
查看
#5楼
2007-12-26 18:33
omnislash
这种情况用回调接口更合适一些
回复
引用
查看
#6楼
2007-12-26 18:34
jillzhang
你这样用事件,出发点是错误的,事件的目的是让类的外部能参与类的动作,而且不分外部的环境
你这样,我觉得用接口比较好
回复
引用
查看
#7楼
[
楼主
] 2007-12-26 18:48
Phoenix
@jillzhang
@留恋星空
@omnislash
呵呵,特定情况当然得特定处理,我们这边的scenario是这样的:大量的输入Form是比较类似的,所以我们为BO做了元数据表,根据BO的元数据来修饰UI控件(BO的展示),比方说长度,帮助信息,校验,格式等等。现在我们修饰一个第三方的Grid控件,其中某一个功能是当Grid中的数据改变掉了,需要进行Validatation,所以在修饰类中是通过Grid的ValidateRow事件来处理的,但问题是,在特殊场景时,这个Grid可以让开发人员手动编写Validatation的处理。所以就出现了以上这种处理。
回复
引用
查看
#8楼
2007-12-27 09:48
新手啊,这名字都有人抢 [未注册用户]
说实话,看了半天发现楼主还是没有解决开头提出的问题。另外我个人觉得事件的默认值不可能是null的。
回复
引用
#9楼
[
楼主
]
2007-12-27 20:19
Phoenix
@新手啊,这名字都有人抢
对于不知道的事情请不要用“觉得”,否则就不敢去尝试,不敢去思考。
回复
引用
查看
新用户注册
刷新评论列表
标题
姓名
主页
Email
(博主才能看到)
验证码
*
看不清,换一张
[
登录
][
注册
]
内容(请不要发表任何与政治相关的内容)
网站首页
新闻频道
社区
小组
博问
网摘
人才
找找看
Remember Me?
登录
使用高级评论
新用户注册
返回页首
恢复上次提交
[使用Ctrl+Enter键可以直接提交]
该文被作者在 2007-12-26 15:04 编辑过
Google站内搜索
China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
近千种 9-95 新二手计算图书火热销售中!
相关文章:
相关链接:
所属分类的其他文章:
Server Explorer disappeared in VS 2008
如何在外部得到一个event是否已被注册
画一个立体的柱图
用纯API写的窗体
最新IT新闻:
微软:不裁员也不削减研发开支
2008年11月22日科技博客精选
诺基亚将支持Lotus Notes 和黑莓争夺市场
Mozilla公布去年收入报告
2008年11月21日科技博客精选
Powered by:
博客园
Copyright © Phoenix