ObjectManager.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using System.Text;
  6. namespace Base
  7. {
  8. public interface IObjectEvent
  9. {
  10. Type ValueType();
  11. void SetValue(object value);
  12. }
  13. public abstract class ObjectEvent<T> : IObjectEvent
  14. {
  15. private T value;
  16. protected T GetValue()
  17. {
  18. return value;
  19. }
  20. public void SetValue(object v)
  21. {
  22. this.value = (T)v;
  23. }
  24. public Type ValueType()
  25. {
  26. return typeof(T);
  27. }
  28. }
  29. public class ObjectManager : IDisposable
  30. {
  31. private readonly Dictionary<string, Assembly> assemblies = new Dictionary<string, Assembly>();
  32. private Dictionary<Type, IObjectEvent> objectEvents;
  33. private readonly Dictionary<long, Object> objects = new Dictionary<long, Object>();
  34. private List<long> starts = new List<long>();
  35. private List<long> newStarts = new List<long>();
  36. private List<long> updates = new List<long>(3000);
  37. private List<long> newUpdates = new List<long>(3000);
  38. private readonly List<long> loaders = new List<long>();
  39. public void Dispose()
  40. {
  41. foreach (Object o in this.objects.Values.ToArray())
  42. {
  43. o.Dispose();
  44. }
  45. }
  46. public void Register(string name, Assembly assembly)
  47. {
  48. this.assemblies[name] = assembly;
  49. objectEvents = new Dictionary<Type, IObjectEvent>();
  50. foreach (Assembly ass in this.assemblies.Values)
  51. {
  52. Type[] types = ass.GetTypes();
  53. foreach (Type type in types)
  54. {
  55. object[] attrs = type.GetCustomAttributes(typeof(ObjectEventAttribute), false);
  56. if (attrs.Length == 0)
  57. {
  58. continue;
  59. }
  60. object obj = Activator.CreateInstance(type);
  61. IObjectEvent objectEvent = obj as IObjectEvent;
  62. if (objectEvent == null)
  63. {
  64. Log.Error($"组件事件没有继承IComponentEvent: {type.Name}");
  65. }
  66. objectEvents[objectEvent.ValueType()] = objectEvent;
  67. }
  68. }
  69. this.Load();
  70. }
  71. public Assembly GetAssembly(string name)
  72. {
  73. return this.assemblies[name];
  74. }
  75. public Assembly[] GetAssemblies()
  76. {
  77. return this.assemblies.Values.ToArray();
  78. }
  79. private void Load()
  80. {
  81. foreach (long id in this.loaders)
  82. {
  83. Object obj;
  84. if (!this.objects.TryGetValue(id, out obj))
  85. {
  86. continue;
  87. }
  88. IObjectEvent objectEvent;
  89. if (!objectEvents.TryGetValue(obj.GetType(), out objectEvent))
  90. {
  91. continue;
  92. }
  93. ILoader iLoader = objectEvent as ILoader;
  94. if (iLoader == null)
  95. {
  96. continue;
  97. }
  98. objectEvent.SetValue(obj);
  99. iLoader.Load();
  100. }
  101. }
  102. public void Add(Object obj)
  103. {
  104. if (objectEvents == null)
  105. {
  106. return;
  107. }
  108. this.objects.Add(obj.Id, obj);
  109. IObjectEvent objectEvent;
  110. if (!objectEvents.TryGetValue(obj.GetType(), out objectEvent))
  111. {
  112. return;
  113. }
  114. IStart iStart = objectEvent as IStart;
  115. if (iStart != null)
  116. {
  117. this.newStarts.Add(obj.Id);
  118. }
  119. IUpdate iUpdate = objectEvent as IUpdate;
  120. if (iUpdate != null)
  121. {
  122. this.newUpdates.Add(obj.Id);
  123. }
  124. ILoader iLoader = objectEvent as ILoader;
  125. if (iLoader != null)
  126. {
  127. this.loaders.Add(obj.Id);
  128. }
  129. }
  130. public void Remove(long id)
  131. {
  132. this.objects.Remove(id);
  133. }
  134. public void Awake(long id)
  135. {
  136. Object obj;
  137. if (!objects.TryGetValue(id, out obj))
  138. {
  139. return;
  140. }
  141. IObjectEvent objectEvent;
  142. if (!objectEvents.TryGetValue(obj.GetType(), out objectEvent))
  143. {
  144. return;
  145. }
  146. IAwake iAwake = objectEvent as IAwake;
  147. if (iAwake == null)
  148. {
  149. return;
  150. }
  151. objectEvent.SetValue(obj);
  152. iAwake.Awake();
  153. }
  154. public void Awake<P1>(long id, P1 p1)
  155. {
  156. Object obj;
  157. if (!objects.TryGetValue(id, out obj))
  158. {
  159. return;
  160. }
  161. IObjectEvent objectEvent;
  162. if (!objectEvents.TryGetValue(obj.GetType(), out objectEvent))
  163. {
  164. return;
  165. }
  166. IAwake<P1> iAwake = objectEvent as IAwake<P1>;
  167. if (iAwake == null)
  168. {
  169. return;
  170. }
  171. objectEvent.SetValue(obj);
  172. iAwake.Awake(p1);
  173. }
  174. public void Awake<P1, P2>(long id, P1 p1, P2 p2)
  175. {
  176. Object obj;
  177. if (!objects.TryGetValue(id, out obj))
  178. {
  179. return;
  180. }
  181. IObjectEvent objectEvent;
  182. if (!objectEvents.TryGetValue(obj.GetType(), out objectEvent))
  183. {
  184. return;
  185. }
  186. IAwake<P1, P2> iAwake = objectEvent as IAwake<P1, P2>;
  187. if (iAwake == null)
  188. {
  189. return;
  190. }
  191. objectEvent.SetValue(obj);
  192. iAwake.Awake(p1, p2);
  193. }
  194. public void Awake<P1, P2, P3>(long id, P1 p1, P2 p2, P3 p3)
  195. {
  196. Object obj;
  197. if (!objects.TryGetValue(id, out obj))
  198. {
  199. return;
  200. }
  201. IObjectEvent objectEvent;
  202. if (!objectEvents.TryGetValue(obj.GetType(), out objectEvent))
  203. {
  204. return;
  205. }
  206. IAwake<P1, P2, P3> iAwake = objectEvent as IAwake<P1, P2, P3>;
  207. if (iAwake == null)
  208. {
  209. return;
  210. }
  211. objectEvent.SetValue(obj);
  212. iAwake.Awake(p1, p2, p3);
  213. }
  214. private void Start()
  215. {
  216. starts = newStarts;
  217. newStarts = new List<long>();
  218. foreach (long id in starts)
  219. {
  220. Object obj;
  221. if (!this.objects.TryGetValue(id, out obj))
  222. {
  223. continue;
  224. }
  225. IObjectEvent objectEvent;
  226. if (!objectEvents.TryGetValue(obj.GetType(), out objectEvent))
  227. {
  228. continue;
  229. }
  230. IStart iStart = objectEvent as IStart;
  231. if (iStart == null)
  232. {
  233. continue;
  234. }
  235. objectEvent.SetValue(obj);
  236. iStart.Start();
  237. }
  238. }
  239. public void Update()
  240. {
  241. this.Start();
  242. // 交换update
  243. List<long> tmpUpdate = updates;
  244. updates = newUpdates;
  245. newUpdates = tmpUpdate;
  246. newUpdates.Clear();
  247. foreach (long id in updates)
  248. {
  249. Object obj;
  250. if (!objects.TryGetValue(id, out obj))
  251. {
  252. continue;
  253. }
  254. IObjectEvent objectEvent;
  255. if (!objectEvents.TryGetValue(obj.GetType(), out objectEvent))
  256. {
  257. continue;
  258. }
  259. IUpdate iUpdate = objectEvent as IUpdate;
  260. if (iUpdate == null)
  261. {
  262. continue;
  263. }
  264. newUpdates.Add(id);
  265. objectEvent.SetValue(obj);
  266. try
  267. {
  268. iUpdate.Update();
  269. }
  270. catch (Exception e)
  271. {
  272. Log.Error(e.ToString());
  273. }
  274. }
  275. }
  276. public override string ToString()
  277. {
  278. var info = new Dictionary<string, int>();
  279. foreach (Object obj in objects.Values)
  280. {
  281. if (info.ContainsKey(obj.GetType().Name))
  282. {
  283. info[obj.GetType().Name] += 1;
  284. }
  285. else
  286. {
  287. info[obj.GetType().Name] = 1;
  288. }
  289. }
  290. info = info.OrderByDescending(s => s.Value).ToDictionary(p => p.Key, p => p.Value);
  291. StringBuilder sb = new StringBuilder();
  292. sb.Append("\r\n");
  293. foreach (string key in info.Keys)
  294. {
  295. sb.Append($"{info[key],10} {key}\r\n");
  296. }
  297. sb.Append($"\r\n start: {newStarts.Count}, update: {newUpdates.Count} total: {this.objects.Count}");
  298. return sb.ToString();
  299. }
  300. }
  301. }