using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading.Tasks; using Aitex.Core.RT.Event; using Aitex.Core.RT.Log; using Aitex.Core.Util; using Aitex.Core.WCF; using MECF.Framework.Common.OperationCenter; namespace Aitex.Core.RT.OperationCenter { public class OperationManager : ICommonOperation, IOperation { private ConcurrentDictionary> _operationMap = new ConcurrentDictionary>(); private ConcurrentDictionary _timeOperationMap = new ConcurrentDictionary(); private Func _isSubscriptionAttribute; private Func _hasSubscriptionAttribute; private Dictionary> _operationInterlockCheck = new Dictionary>(); public event Func OnDoOperation; public void Initialize(bool enableService) { _isSubscriptionAttribute = (object attribute) => attribute is SubscriptionAttribute; _hasSubscriptionAttribute = (MemberInfo mi) => mi.GetCustomAttributes(inherit: false).Any(_isSubscriptionAttribute); OP.InnerOperationManager = this; OP.OperationManager = this; if (enableService) { Singleton.Instance.Initialize(new Type[1] { typeof(InvokeService) }); } } public void Initialize() { Initialize(enableService: true); } public void Subscribe(T instance, string keyPrefix = null) where T : class { if (instance == null) { throw new ArgumentNullException("instance"); } Traverse(instance, keyPrefix); } public void Subscribe(string key, OperationFunction op) { if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentNullException("key"); } if (_timeOperationMap.ContainsKey(key)) { throw new Exception($"Duplicated Key:{key}"); } if (op == null) { throw new ArgumentNullException("op"); } _timeOperationMap[key] = op; } public void Subscribe(string key, Func op) { if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentNullException("key"); } if (_operationMap.ContainsKey(key)) { throw new Exception($"Duplicated Key:{key}"); } if (op == null) { throw new ArgumentNullException("op"); } _operationMap[key] = op; } public bool DoOperation(string operation, out string reason, int time, params object[] args) { if (!CanDoOperation(operation, out reason, args)) { EV.PostWarningLog("OP", "Can not execute " + operation + ", " + reason); return false; } if (!_timeOperationMap[operation](out reason, time, args)) { LOG.Error("Do operation " + operation + " failed, " + reason); return false; } return true; } public bool ContainsOperation(string operation) { return _timeOperationMap.ContainsKey(operation) || _operationMap.ContainsKey(operation); } public bool AddCheck(string operation, IInterlockChecker check) { if (!_operationInterlockCheck.ContainsKey(operation)) { _operationInterlockCheck[operation] = new List(); } _operationInterlockCheck[operation].Add(check); return true; } public bool CanDoOperation(string operation, out string reason, params object[] args) { if (!ContainsOperation(operation)) { reason = "Call unregistered function, " + operation; return false; } if (_operationInterlockCheck.ContainsKey(operation)) { foreach (IInterlockChecker item in _operationInterlockCheck[operation]) { if (!item.CanDo(out reason, args)) { return false; } } } reason = string.Empty; return true; } public bool DoOperation(string operation, params object[] args) { if (this.OnDoOperation != null && this.OnDoOperation(operation, args)) { return true; } if (!ContainsOperation(operation)) { throw new ApplicationException("调用了未发布的接口" + operation); } if (!CanDoOperation(operation, out var reason, args)) { EV.PostWarningLog("OP", "Can not execute " + operation + ", " + reason); return false; } string text = ""; if (args == null || args.Length == 0) { text = "()"; } else { text += "("; foreach (object obj in args) { if (obj == null) { continue; } string text2 = ""; if (obj.GetType() == typeof(Dictionary)) { text2 += "["; foreach (KeyValuePair item in (Dictionary)obj) { string text3 = item.Value.ToString(); if (text3.Length > 10) { text3 = text3.Substring(0, 7) + "..."; } text2 += item.Value.ToString(); text2 += ", "; } if (text2.Length > 2) { text2 = text2.Remove(text2.Length - 2, 2); } text2 += "]"; text += text2; } else { text += obj.ToString(); } text += ", "; } if (text.Length > 2) { text = text.Remove(text.Length - 2, 2); } text += ")"; } if (text.Length > 50) { text = text.Substring(0, 50) + "..."; LOG.Write("long parameter: " + text); } EV.PostInfoLog("OP", "Invoke operation " + operation + text); string reason2; if (_operationMap.ContainsKey(operation)) { _operationMap[operation](operation, args); } else if (!_timeOperationMap[operation](out reason2, 0, args)) { EV.PostWarningLog("OP", reason2); return false; } return true; } public void Traverse(object instance, string keyPrefix) { Parallel.ForEach(((IEnumerable)instance.GetType().GetMethods()).Where((Func)_hasSubscriptionAttribute), delegate(MethodInfo fi) { string text = Parse(fi); text = (string.IsNullOrWhiteSpace(keyPrefix) ? text : $"{keyPrefix}.{text}"); }); } private string Parse(MethodInfo member) { return _hasSubscriptionAttribute(member) ? (member.GetCustomAttributes(inherit: false).First(_isSubscriptionAttribute) as SubscriptionAttribute).Key : null; } } }