OperationManager.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. using Aitex.Core.RT.OperationCenter;
  2. using MECF.Framework.Common.OperationCenter;
  3. using System;
  4. using System.Collections.Concurrent;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Reflection;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10. using Aitex.Core.Util;
  11. namespace Common.OP
  12. {
  13. public class OperationManager : ICommonOperation, IOperation
  14. {
  15. private ConcurrentDictionary<string, Func<string, object[], bool>> _operationMap = new ConcurrentDictionary<string, Func<string, object[], bool>>();
  16. private ConcurrentDictionary<string, OperationFunction> _timeOperationMap = new ConcurrentDictionary<string, OperationFunction>();
  17. private Func<object, bool> _isSubscriptionAttribute;
  18. private Func<MemberInfo, bool> _hasSubscriptionAttribute;
  19. private Dictionary<string, List<IInterlockChecker>> _operationInterlockCheck = new Dictionary<string, List<IInterlockChecker>>();
  20. public OperationManager()
  21. {
  22. }
  23. public void Initialize(bool enableService)
  24. {
  25. _isSubscriptionAttribute = attribute => attribute is SubscriptionAttribute;
  26. _hasSubscriptionAttribute = mi => mi.GetCustomAttributes(false).Any(_isSubscriptionAttribute);
  27. OP.InnerOperationManager = this;
  28. OP.OperationManager = this;
  29. if (enableService)
  30. {
  31. //Singleton<WcfServiceManager>.Instance.Initialize(new Type[]
  32. //{
  33. // typeof(InvokeService)
  34. //});
  35. }
  36. }
  37. public void Initialize()
  38. {
  39. Initialize(true);
  40. }
  41. public void Subscribe<T>(T instance, string keyPrefix = null) where T : class
  42. {
  43. if (instance == null)
  44. throw new ArgumentNullException("instance");
  45. Traverse(instance, keyPrefix);
  46. }
  47. public void Subscribe(string key, OperationFunction op)
  48. {
  49. if (string.IsNullOrWhiteSpace(key))
  50. throw new ArgumentNullException("key");
  51. if (_timeOperationMap.ContainsKey(key))
  52. throw new Exception(string.Format("Duplicated Key:{0}", key));
  53. if (op == null)
  54. throw new ArgumentNullException("op");
  55. _timeOperationMap[key] = op;
  56. }
  57. public void Subscribe(string key, Func<string, object[], bool> op)
  58. {
  59. if (string.IsNullOrWhiteSpace(key))
  60. throw new ArgumentNullException("key");
  61. if (_operationMap.ContainsKey(key))
  62. throw new Exception(string.Format("Duplicated Key:{0}", key));
  63. if (op == null)
  64. throw new ArgumentNullException("op");
  65. _operationMap[key] = op;
  66. }
  67. /// <summary>
  68. ///
  69. /// </summary>
  70. /// <param name="operation">操作名</param>
  71. /// <param name="time">毫秒</param>
  72. /// <param name="reason">失败原因</param>
  73. /// <param name="args">参数</param>
  74. /// <returns></returns>
  75. public bool DoOperation(string operation, out string reason, int time, params object[] args)
  76. {
  77. if (!CanDoOperation(operation, out reason, args))
  78. {
  79. //EV.PostWarningLog("OP", $"Can not execute {operation}, {reason}");
  80. return false;
  81. }
  82. if (!_timeOperationMap.ContainsKey(operation) || !_timeOperationMap[operation].Invoke(out reason, time, args))
  83. {
  84. //LOG.Error($"Do operation {operation} failed, {reason}");
  85. return false;
  86. }
  87. return true;
  88. }
  89. public bool ContainsOperation(string operation)
  90. {
  91. return _timeOperationMap.ContainsKey(operation) || _operationMap.ContainsKey(operation);
  92. }
  93. public bool AddCheck(string operation, IInterlockChecker check)
  94. {
  95. if (!_operationInterlockCheck.ContainsKey(operation))
  96. _operationInterlockCheck[operation] = new List<IInterlockChecker>();
  97. _operationInterlockCheck[operation].Add(check);
  98. return true;
  99. }
  100. public bool CanDoOperation(string operation, out string reason, params object[] args)
  101. {
  102. if (!ContainsOperation(operation))
  103. {
  104. reason = $"Call unregistered function, {operation}";
  105. return false;
  106. }
  107. if (_operationInterlockCheck.ContainsKey(operation))
  108. {
  109. foreach (var interlockChecker in _operationInterlockCheck[operation])
  110. {
  111. if (!interlockChecker.CanDo(out reason, args))
  112. {
  113. return false;
  114. }
  115. }
  116. }
  117. reason = string.Empty;
  118. return true;
  119. }
  120. public bool DoOperation(string operation, params object[] args)
  121. {
  122. if (!ContainsOperation(operation))
  123. {
  124. throw new ApplicationException("调用了未发布的接口" + operation);
  125. }
  126. if (!CanDoOperation(operation, out string reason, args))
  127. {
  128. //EV.PostWarningLog("OP", $"Can not execute {operation}, {reason}");
  129. return false;
  130. }
  131. string parameter = "";
  132. if (args.Length == 0)
  133. parameter = "()";
  134. else
  135. {
  136. parameter += "(";
  137. foreach (object o in args)
  138. {
  139. var param1 = "";
  140. if (o.GetType() == typeof(Dictionary<string, object>))
  141. {
  142. param1 += "[";
  143. foreach (var item in (Dictionary<string, object>)(o))
  144. {
  145. var value = item.Value.ToString();
  146. if (value.Length > 10)
  147. value = value.Substring(0, 7) + "...";
  148. param1 += item.Value.ToString();
  149. param1 += ", ";
  150. }
  151. if (param1.Length > 2)
  152. param1 = param1.Remove(param1.Length - 2, 2);
  153. param1 += "]";
  154. parameter += param1;
  155. }
  156. else
  157. {
  158. parameter += o.ToString();
  159. }
  160. parameter += ", ";
  161. }
  162. if (parameter.Length > 2)
  163. parameter = parameter.Remove(parameter.Length - 2, 2);
  164. parameter += ")";
  165. }
  166. if (parameter.Length > 50)
  167. {
  168. parameter = parameter.Substring(0, 50) + "...";
  169. //LOG.Write("long parameter: " + parameter);
  170. }
  171. if (operation != "PMB.SetPMBChillerState")
  172. //EV.PostInfoLog("OP", $"Invoke operation {operation}{parameter}");
  173. if (_operationMap.ContainsKey(operation))
  174. {
  175. _operationMap[operation](operation, args);
  176. }
  177. else
  178. {
  179. if (!_timeOperationMap[operation].Invoke(out string reason1, 0, args))
  180. {
  181. //EV.PostWarningLog("OP", reason);
  182. return false;
  183. }
  184. }
  185. return true;
  186. }
  187. public void Traverse(object instance, string keyPrefix)
  188. {
  189. Parallel.ForEach(instance.GetType().GetMethods().Where<MethodInfo>(_hasSubscriptionAttribute), fi =>
  190. {
  191. string key = Parse(fi);
  192. key = string.IsNullOrWhiteSpace(keyPrefix) ? key : string.Format("{0}.{1}", keyPrefix, key);
  193. //Subscribe(key, fi.Invoke(instance, );
  194. });
  195. }
  196. string Parse(MethodInfo member)
  197. {
  198. return _hasSubscriptionAttribute(member) ? (member.GetCustomAttributes(false).First(_isSubscriptionAttribute) as SubscriptionAttribute).Key : null;
  199. }
  200. }
  201. }