委托在项目中应用(收集汇总)

委托回调是项目中消息床传递用得最多的。u3d中虽然有sendmessage方法。但远远没有委托发送消息好。当然。这里不仅仅是用于u3d中

先来看一个全局的消息处理类eventd.cs

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6
 7 namespace eventd
 8 {
 9     /// 消息码定义(最好定义到各个服务自己的头文件中)
10     public enum Evt
11     {
12         Invalid = 0,                        /// 无效事件
13
14         // 状态事件//
15         ConnectStateChanged,                /// 连接状态改变//
16         Disconnection,                      /// 连接断开//
17         //其他状态
18         Max
19     }
20
21     /// <summary>
22     /// 需要传递事件数据的类
23     /// </summary>
24     public class EventArgs_Animal : EventArgs
25     {
26         public int type;
27         public string name;
28     }
29 }

全局消息定义

然后一个事件系统。用于发布事件和订阅消息EventSystem.cs

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6
  7 namespace eventd
  8 {
  9
 10     class EventKey
 11     {
 12         public ushort eventId = 0;            // event id
 13         public uint uniqueKey = 0;            // event source id
 14     }
 15
 16     class EventKeyEqualityComparer : IEqualityComparer<EventKey>
 17     {
 18         public bool Equals(EventKey k1, EventKey k2)
 19         {
 20             return (k1.eventId == k2.eventId && k1.uniqueKey == k2.uniqueKey);
 21         }
 22
 23         public int GetHashCode(EventKey ek)
 24         {
 25             int hCode = (int)((uint)((ek.uniqueKey & 0xFFFF) << 16) + (uint)ek.eventId);
 26             //int hCode = ek.uniqueKey ^ (uint)ek.eventId;
 27             return hCode.GetHashCode();
 28         }
 29     }
 30
 31     public delegate void EventHandler(ushort eventId, uint uniqueKey, EventArgs args);
 32
 33
 34     /// 事件订阅信息
 35     class SubscribeInfo
 36     {
 37         public event EventHandler eventHandler = null;
 38         public int callCount = 0;
 39
 40         public void Attach(EventHandler eventHandler)
 41         {
 42             this.eventHandler += eventHandler;
 43         }
 44
 45         public void Detach(EventHandler eventHandler)
 46         {
 47             this.eventHandler -= eventHandler;
 48         }
 49
 50         public void Emit(ushort eventId, uint uniqueKey, EventArgs args)
 51         {
 52             if (eventHandler != null)
 53             {
 54                 callCount++;
 55
 56                 // 加入异常捕捉,防止异常后导致callCount不递减,从而引发不真实的错误
 57                 try
 58                 {
 59                     this.eventHandler(eventId, uniqueKey, args);
 60                 }
 61                 catch (Exception e)
 62                 {
 63                     //Log.Trace("Event callback exception, EventId: " + eventId);
 64                     //Debug.LogException(e);
 65                 }
 66
 67                 callCount--;
 68             }
 69         }
 70
 71         public bool CanRemove()
 72         {
 73             return (eventHandler == null);
 74         }
 75     }
 76
 77     public class EventSystem
 78     {
 79         private Dictionary<EventKey, SubscribeInfo> mEventHandlerMap = null;
 80         private int mEmitDepth = 0;
 81         private const int MAX_EMIT_DEPTH = 20;
 82         private int[] mEventIdStack = new int[MAX_EMIT_DEPTH];
 83
 84         //public static readonly EventSystem Instance = new EventSystem();
 85         private static EventSystem sInstance = null;
 86         public static EventSystem Instance
 87         {
 88             get
 89             {
 90                 if (sInstance == null)
 91                     sInstance = new EventSystem();
 92                 return sInstance;
 93             }
 94         }
 95
 96         private EventSystem()
 97         {
 98             EventKeyEqualityComparer comp = new EventKeyEqualityComparer();
 99             mEventHandlerMap = new Dictionary<EventKey, SubscribeInfo>(comp);
100         }
101
102         /// <summary>
103         /// 注册事件
104         /// </summary>
105         /// <param name="handler">方法名</param>
106         /// <param name="eventId"></param>
107         /// <param name="uniqueKey"></param>
108         /// <returns></returns>
109         public bool AddListener(EventHandler handler, ushort eventId, uint uniqueKey)
110         {
111             if (handler == null)
112                 return false;
113
114             EventKey ek = new EventKey();
115             ek.eventId = eventId;
116             ek.uniqueKey = uniqueKey;
117
118             if (mEventHandlerMap.ContainsKey(ek))
119             {
120                 SubscribeInfo si = mEventHandlerMap[ek];
121                 si.Attach(handler);
122             }
123             else
124             {
125                 SubscribeInfo si = new SubscribeInfo();
126                 si.Attach(handler);
127
128                 mEventHandlerMap.Add(ek, si);
129             }
130
131             return true;
132         }
133
134         public void RemoveListener(EventHandler handler, ushort eventId, uint uniqueKey)
135         {
136             if (handler == null)
137                 return;
138
139             EventKey ek = new EventKey();
140             ek.eventId = eventId;
141             ek.uniqueKey = uniqueKey;
142
143             if (mEventHandlerMap.ContainsKey(ek))
144             {
145                 SubscribeInfo si = mEventHandlerMap[ek];
146                 si.Detach(handler);
147             }
148         }
149
150
151         public void Emit(ushort eventId, uint uniqueKey, EventArgs args)
152         {
153             EventKey ek = new EventKey();
154             ek.eventId = eventId;
155
156             // 先发送有源指针的
157             ek.uniqueKey = uniqueKey;
158             if (ek.uniqueKey != 0)
159             {
160                 _Emit(ek, eventId, uniqueKey, args);
161             }
162
163             // 然后发送没有源指针的
164             ek.uniqueKey = 0;
165             _Emit(ek, eventId, uniqueKey, args);
166         }
167
168
169         private bool _Emit(EventKey ek, ushort eventId, uint uniqueKey, EventArgs args)
170         {
171             mEmitDepth++;
172
173             if (mEmitDepth > 0 && mEmitDepth <= MAX_EMIT_DEPTH)
174                 mEventIdStack[mEmitDepth - 1] = eventId;
175             if (mEmitDepth >= MAX_EMIT_DEPTH)
176             {
177                 //Console.WriteLine("Event engine error, endless loop, EventID: " + eventId);
178
179                 printCallstack();
180
181                 mEmitDepth--;
182
183                 return false;
184             }
185
186             if (mEventHandlerMap.ContainsKey(ek))
187             {
188                 SubscribeInfo si = mEventHandlerMap[ek];
189
190                 if (si.callCount >= 5)
191                 {
192                     //Console.WriteLine("Fatal error, an event is endless loop, EventID: " + eventId);
193
194                     printCallstack();
195
196                     mEmitDepth--;
197
198                     return false;
199                 }
200
201
202                 if (si.CanRemove())
203                 {
204                     mEventHandlerMap.Remove(ek);
205                 }
206                 else
207                 {
208                     si.Emit(eventId, uniqueKey, args);
209                 }
210             }
211
212             mEmitDepth--;
213
214             return true;
215         }
216
217         private void printCallstack()
218         {
219             string osb = "";
220             for (int i = 0; i < mEmitDepth; i++)
221             {
222                 osb += mEventIdStack[i] + ",";
223             }
224             //Console.WriteLine("Event callstack: " + osb);
225         }
226
227     }
228 }

事件系统

模拟:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6
 7 namespace eventd
 8 {
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13             Program p = new Program();
14             p.AddEvents(); //注册事件
15
16             string str = Console.ReadLine();
17
18             //模拟断开连接
19             if (str == "1")
20             {
21                 //消息,跟根据自己需要
22                 EventArgs_Animal animal = new EventArgs_Animal();
23                 animal.type = 20;
24                 animal.name = "姓名";
25
26                 //无事件数据
27                 //EventSystem.Instance.Emit((ushort)Evt.ConnectStateChanged, 0, null);
28
29                 //有事件数据
30                 //连接断开。触发事件
31                 EventSystem.Instance.Emit((ushort)Evt.ConnectStateChanged, 0, animal);
32             }
33
34             Console.ReadLine();
35         }
36
37         public void AddEvents()
38         {
39             //EventSystem.Instance.AddListener(OnUpdateChatMessage, (ushort)Evt.UpdateChatMessage, 0);
40
41             //注册事件。当ConnectStateChanged 即断开连接时候触发
42             EventSystem.Instance.AddListener(onUpdate, (ushort)Evt.ConnectStateChanged, 0);
43         }
44         //public override void RemoveEvents()
45         /// <summary>
46         /// 移除事件
47         /// </summary>
48         public void RemoveEvents()
49         {
50             //   base.RemoveEvents();
51
52             EventSystem.Instance.RemoveListener(onUpdate, (ushort)Evt.ConnectStateChanged, 0);
53         }
54         // public delegate void EventHandler(ushort eventId, uint uniqueKey, EventArgs args);
55         void onUpdate(ushort eventId, uint uniqueKey, EventArgs args)
56         {
57             EventArgs_Animal a = args as EventArgs_Animal;
58
59             if (a != null)
60             {
61                 Console.WriteLine(a.name);
62                 Console.WriteLine(a.type);
63             }
64             Console.WriteLine("回调");
65         }
66     }
67 }

看完之后你不是会问。这有什么意义啊。

用这句

EventSystem.Instance.Emit((ushort)Evt.ConnectStateChanged, 0, animal);

直接代替onUpdate()方法不就可以了吗?写这么多好麻烦?

这里只是演示。触发订阅者的方法的代码。不一定非得跟方法在一个类。

就拿我这个演示的来说。我在A类注册了事件。那就很显示onUpdate方法在A类中

可以在B类触发。也就是在B类执行代码

EventSystem.Instance.Emit((ushort)Evt.ConnectStateChanged, 0, animal);

时间: 2024-10-07 12:04:04

委托在项目中应用(收集汇总)的相关文章

记一次项目中的查询汇总

项目要实现查询汇总的功能,针对不同的分组实现不同的汇总.直接上图吧,直观一点.要实现的效果如下图所示. 设计思路:第一,先实现电业局,变电工区,运维站,变电所相同的列名称,能够合并的功能.第二,在合适的位置插入汇总行(即有总计的行). 实现方法,第一,相同的列名称合并的功能,很简单,设置要合并的列的列属性AllowMerge=true,并不总的GridView的AllowMerge设为true即可. 第二,主要难点在怎么实现汇总的功能.数据库中的获取的数据如下图所示: 数据说明: PERSONI

node.js项目中使用coffeescript的方式汇总

Coffeescript作为Javascript低调的小弟实在是有过人之处,使用它可以增进开发效率,减少代码错误, 关键是能大幅提升开发愉悦感.我越来越觉得只要可能就在自己的项目中把coffee用起来. 然而也许你和我一样,在了解完coffeescript的语法后准备一试身手的时候,却面对如何把它引入项目而犯起愁来. 其实coffeescript这种语言因其可以一对一地翻译为javascript的特性,使用起来其实非常灵活. 将其引入项目的方式也不止一个.这里,我先就node项目引入coffee

转:Qt项目中遇到的一些小问题汇总

链接:http://blog.csdn.net/yangyunfeizj/article/details/7082001    作者:GoatYangYang 公司让负责qt界面开发,但是接触qt又不久,现将在项目中遇到的一些问题汇总下,一为了避免自己忘记,二希望能帮助到他人. 1.在程序关闭窗口时,显示提示窗口: qt中有很多信号和相应的槽函数,上述问题需要拦截关闭窗口信息QWidget::close(),QWidget::closeEvent( QCloseEvent * event )重写

iOS总结:项目中的各种小坑汇总

一.字符串转JSON 在网络请求时,如果服务端返回的是字符串,那么就需要我们自己封装一个类,将请求下来的字符串转换成json对象,从而存入模型中. 注意: 字符串中如果含有一些特殊转意符(如\n.\t等),需要先对字符串进行处理. 示例代码如下: +(NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString{ if (jsonString == nil) { return nil; } jsonString = [jsonStr

最全面的iOS和Mac开源项目和第三方库汇总

UI 下拉刷新 EGOTableViewPullRefresh – 最早的下拉刷新控件. SVPullToRefresh – 下拉刷新控件. MJRefresh – 仅需一行代码就可以为UITableView或者CollectionView加上下拉刷新或者上拉刷新功能.可以自定义上下拉刷新的文字说明.具体使用看“使用方法”. (国人写) XHRefreshControl – XHRefreshControl 是一款高扩展性.低耦合度的下拉刷新.上提加载更多的组件.(国人写) CBStoreHou

项目管理中的知识点汇总

项目经理如何分配任务 转载文章,如有再转载,请注明原文出处:http://blog.csdn.net/yihui823/article/details/6778351 记得自己第一次当PM.那是接手的项目,原来的PM,在项目需求分析做完之后,去接手另一个重要的项目去了.当时我和另外两个小组长,自然就成了接手PM的人选.最终原PM选择了我做他的接班人.而我当时最头疼的就是,我怎么给另外两个小组长分配任务啊.前一天大家还... 一位项目经理的个人体会 -转自<天涯>论坛,根据帖子内容整理,原帖地址

Swift项目兼容Objective-C问题汇总

本文是投稿文章,作者:一叶(博客)欢迎将原创文章或者译文投给我们,投稿方式:[email protected]或者在首页点击“投稿爆料” 一.解决问题 Swift 项目需要使用封装好的Objective-c组件.第三方类库,苹果提供的解决方案能够处理日常大部分需求,但还不能称之为完美,混编过程中会遇到很多问 题.本文将Swift兼容Objective-c的问题汇总,以帮助大家更好的使用Swift,内容列表如下: 1. Swift调用Objective-c代码 2. Objective-c调用Sw

iOS:项目中疑难Crash问题集锦

项目中疑难Crash问题集锦 iOS App运行中遇到Crash的情况相信大家都遇到过,开发和者测试中遇到了可能很方便的办法就是直接拿着设备连接一下,然后使用Xcode自带的工具就可以解析出Crash地址了.对于线上App运行时的Crash收集也有很多好用的第三方工具,具有代表性的就是Crashlytics,通过打包时上传dSYM文件,收集到的Crash就可以解析为可读的格式了. 尽管Crashlytics功能已经很强大了,统计出来的Crash信息也足够详细,还是会有一些难缠的问题,例如程序直接

谈谈MVC项目中的缓存功能设计的相关问题

本文收集一些关于项目中为什么需要使用缓存功能,以及怎么使用等,在实际开发中对缓存的设计的考虑 为什么需要讨论缓存呢? 缓存是一个中大型系统所必须考虑的问题.为了避免每次请求都去访问后台的资源(例如数据库),我们一般会考虑将一些更新不是很频繁的,可以重用的数据,通过一定的方式临时地保存起来,后续的请求根据情况可以直接访问这些保存起来的数据.这种机制就是所谓的缓存机制. 根据缓存的位置不同,可以区分为: 1.客户端缓存(缓存在用户的客户端,例如浏览器) 2.服务器断货(缓存在服务器中,可以缓存在内存