登录
注册
首页
C#
WinForm
Asp.net
WebService
LINQ
Silverlight
WPF
WCF
算法/数据结构
设计模式GOF
组件/控件开发
MSSQL
JavaScript
星辰.Net技术社区
.NET
C#
C#如何判断一个事件是否已被注册
输入您的搜索字词
提交搜索表单
Web
www.netcsharp.cn
.NET
C#
WinForm
ASP.NET
WebService
LINQ
WPF
WCF
Silverlight
组件/控件开发
设计模式GOF
算法/数据结构
数据库
MSSQL
MYSQL
Oracle
脚本
JavaScript
Python
社区项目
DNTShell
其他
资源共享
问题区
生活杂谈
基础理论
1
/ 1 页
1
跳转
页
查看:
224
[高级] C#如何判断一个事件是否已被注册
本主题由 管理员 admin 于 2008-7-11 17:51:26 执行 主题分类 操作
admin
admin
相册
组别:
管理员
性别:
来自:
积分:
1026
帖子:
1020
注册:
2008-03-05
2008-05-21 12:34
|
只看楼主
树型
|
收藏
|
小
中
大
1
C#如何判断一个事件是否已被注册
同事有个这样的需求:需要判断一个对象的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变得非常多时,查询的效率会变得非常差.
发送短消息
查看公共资料
查找该会员全部帖子
UID:
1
精华:
0
威望:
6
金钱:
252.35 元
状态:
在线
<<
上一主题
|
下一主题
>>
1
/ 1 页
1
跳转
页
论坛跳转...
.NET
C#
WinForm
ASP.NET
WebService
LINQ
WPF
WCF
Silverlight
组件/控件开发
设计模式GOF
算法/数据结构
数据库
MSSQL
MYSQL
Oracle
脚本
JavaScript
JQuery
Python
社区项目
DNTShell
其他
资源共享
问题区
生活杂谈
基础理论
我的主题
我的帖子
我的精华
我的相册
帖子标题
空间日志
相册标题
作 者