CLR 显示实现事件 EventSet内部管理一个字典
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace ConsoleApplication5
{
public sealed class EventKey { }
public sealed class EventSet
{
//内部管理一个事件的字典,key为每次生成的所以哈希码是不同的,以确认字典的键不会重复
private readonly Dictionary<EventKey, Delegate> m_events = new Dictionary<EventKey, Delegate>();
/// <summary>
/// Monitor.Enter线程安全,在指定对象上获取排它锁
/// </summary>
/// <param name="eventKey"></param>
/// <param name="handle"></param>
public void Add(EventKey eventKey,Delegate handle)
{
//获取指定对象上的排它锁,线程安全,确保我在增加一个键值对的时候不会发生导致线程不安全的情况
Monitor.Enter(m_events);
Delegate d;
//获取指定键相关联的值,关键是这样可以防止字典的键不存在时,还要写代码去判断键是否存在的情况
m_events.TryGetValue(eventKey, out d);
//将两个委托的调用列表链接在一起
m_events[eventKey] = Delegate.Combine(d, handle);
//释放指定对象上的排它锁
Monitor.Exit(m_events); }
public void Remove(EventKey eventKey, Delegate handler)
{
Monitor.Enter(m_events);
Delegate d;
if (m_events.TryGetValue(eventKey, out d))
{
//从指定的源上删除某个委托,内部执行多路广播委托,删除后委托链的头部地址会改变
d = Delegate.Remove(d, handler); //删除后还有委托,设置新的头部地址
if (d != null)
{
m_events[eventKey] = d;
}
else
{
m_events.Remove(eventKey);
}
Monitor.Exit(m_events); }
}
//激发事件委托
public void Raise(EventKey eventKey, Object sender, EventArgs e)
{
Delegate d;
Monitor.Enter(m_events);
m_events.TryGetValue(eventKey,out d);
Monitor.Exit(m_events);
if (d != null)
{
d.DynamicInvoke(new object[] {sender,e });
}
} }
public class FooEventArgs : EventArgs { }
public class TypeWithLotsOfEvents
{ private readonly EventSet m_eventSet = new EventSet();
protected EventSet EventSet { get { return m_eventSet; } }
//对于TypeWithLotsOfEvents的每个实例对应的 下列字段key是唯一的
protected static readonly EventKey s_fooEventKey = new EventKey(); public event EventHandler<FooEventArgs> FOO
{
add { m_eventSet.Add(s_fooEventKey, value); }
remove { m_eventSet.Remove(s_fooEventKey, value); }
} protected virtual void OnFOO(FooEventArgs e)
{
m_eventSet.Raise(s_fooEventKey, this, e);
}
public void SimulateFOO()
{
OnFOO(new FooEventArgs());
} }
class Program
{
static void Main(string[] args)
{
TypeWithLotsOfEvents twle = new TypeWithLotsOfEvents();
twle.FOO += Twle_FOO;
twle.SimulateFOO();
Console.ReadKey(); } private static void Twle_FOO(object sender, FooEventArgs e)
{
Console.WriteLine("Hading Foo Event here...");
}
}
}
CLR 显示实现事件 EventSet内部管理一个字典的更多相关文章
- [转]3天搞定的小型B/S内部管理类软件定制开发项目【软件开发实战10步骤详解】
本文转自:http://www.cnblogs.com/jirigala/archive/2010/10/07/1845275.html 2010-10-07 21:39 by 通用C#系统架构, 5 ...
- 关于vue事件监听的一个问题
由于新工作需要用vue,所以最近接触最多的也是vue,因为之前一直在用react,所以对于vue上手还是很快的.我也尽量找一些他们两个的异同点,除了多了一些辅助用的方法以外,最大的不同应该是对于组件间 ...
- [CLR via C#]21. 自动内存管理(垃圾回收机制)
目录 理解垃圾回收平台的基本工作原理 垃圾回收算法 垃圾回收与调试 使用终结操作来释放本地资源 对托管资源使用终结操作 是什么导致Finalize方法被调用 终结操作揭秘 Dispose模式:强制对象 ...
- Android软键盘的隐藏显示、事件监听的代码
把开发过程中重要的一些内容片段做个珍藏,如下资料是关于Android软键盘的隐藏显示.事件监听的内容,应该是对小伙伴们有所用途. public class ResizeLayout extends L ...
- CLR VIA C#事件
事件是类型的一个成员,用来在事情发生的时候通知注册了该事件的成员. 事件和观察者模式十分的相似,所以事件应该提供如下几种能力 1.能让对象的方法登记对他的关注 2.能让对象的方法取消对他的关注 3.能 ...
- js闭包(函数内部嵌套一个匿名函数:这个匿名函数可将所在函数的局部变量常驻内存)
js闭包(函数内部嵌套一个匿名函数:这个匿名函数可将所在函数的局部变量常驻内存) 一.总结 1.闭包:就是在一个函数内部嵌套一个匿名函数,这个匿名函数可以访问这个函数的变量. 二.要点 闭包 闭包的相 ...
- 一个字典通过dictionaryWithDictionary 他们的内存指针是不同的
一个字典通过dictionaryWithDictionary 他们的内存指针是不同的 来自为知笔记(Wiz)
- 有一个字典对象,d = {'a':1,'b':2},请用尽量简洁的代码将d转换成{1: 'a', 2: 'b'}
题目:有一个字典对象,d = {'a':1,'b':2},请用尽量简洁的代码将d转换成{1: 'a', 2: 'b'} 第一种方法: d = {'a': 1, 'b': 2}d = {value: k ...
- Python把两个列表合成一个字典
简单粗暴上代码 A= [] B = [] C= dict(map(lambda x,y:[x,y],A,B)) 酱紫,就合成了一个字典
随机推荐
- Socket通信简单实例(WCF调用Socket)
服务端: 控制台程序监听 /// <summary> /// Server /// </summary> class Program { static Socket serve ...
- AppScan 8.0.3安全漏洞扫描总结
本文记录了通过AppScan 8.0.3工具进行扫描的安全漏洞问题以及解决方案, 1.使用SQL注入的认证旁路 问题描述: 解决方案: 一般通过XSSFIlter过滤器进行过滤处理即可,通过XSSFI ...
- Dedesql数据库类详解(二次开发必备教程)(转)
http://www.dedecms.com/help/development/2009/1028/1076.html 织梦DedeCMS的二次开发不仅仅是会写写织梦的标签,会制作织梦的模板.很多时候 ...
- linux基础(3)
一 正文处理命令及tar命令 使用cat命令进行文件的纵向合并 两种文件的纵向合并方法 : tar命令的功能 : 掌握tar命令的功能:将多个文件(也可能包括目录,因为目录本身也是文件)放在一起存 ...
- AppCan上下拉列表刷新
function initBounce(funcTop, funcBottom){ uexWindow.setBounce("1"); if (!funcTop && ...
- java图形化界面-------鼠标监听画圆----------使用匿名类
package com.aa; import java.awt.Color; import java.awt.Graphics; import java.awt.event.MouseAdapter; ...
- HDU 1166 敌兵布阵 树状数组小结(更新)
树状数组(Binary Indexed Tree(BIT), Fenwick Tree) 是一个查询和修改复杂度都为log(n)的数据结构.主要用于查询任意两位之间的所有 元素之和,但是每次只能修改一 ...
- python学习(十三) 数据库支持
13.1 Python数据库编程接口(API) 13.1.1 全局变量 13.1.2 异常 13.1.3 连接和游标 13.1.4 类型 13.2 SQLite和PySQlite 13.2.1 入门 ...
- hardentools
Hardentools是一组简单的实用程序,旨在禁用操作系统(Microsoft Windows,现在)以及主要的消费者应用程序公开的许多“功能”.这些通常为企业客户所设想的功能,对于普通用户来说通 ...
- List批量赋值的几种方法
List<int> list = new List<int>();list.AddRange(new int[] { 1, 5, 10, 20 ,33 }); //也可直接赋值 ...