码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-11-28 16:24:40      阅读:225      评论:0      收藏:0      [点我收藏+]

标签:

委托回调是项目中消息床传递用得最多的。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);

 

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

标签:

原文地址:http://www.cnblogs.com/nsky/p/5002696.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!