using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections.Concurrent; using System.Reflection; using System.Threading.Tasks; using Aitex.Core.Util; using System.Windows; using System.Windows.Media; using System.Windows.Controls; using System.Windows.Data; using Aitex.Core.RT.Log; using Aitex.Core.UI.Control; using System.Windows.Input; namespace Aitex.Core.UI.MVVM { /* * 要求绑定的格式参考如下方式,命名统一为ElementData,这样才能统一由程序把需要从RT获取的数据项名称自动添加进来 */ public class SubscriptionViewModelBase : TimerViewModelBase { const string BindingPathName = "ElementData"; protected Func, Dictionary> PollDataFunction; protected Action InvokeFunction; protected Action DeviceFunction; protected Action DeviceControlFunction; protected Dictionary> PreCommand = new Dictionary>(); ConcurrentBag _subscribedKeys = new ConcurrentBag(); Func _isSubscriptionAttribute; Func _hasSubscriptionAttribute; public ICommand InvokeCommand { get; set; } List> _lstICommand = new List>(); /// /// 设备名称,设备操作 /// public ICommand DeviceCommand { get; set; } public ICommand DeviceControlCommand { get; set; } public SubscriptionViewModelBase(string name) : base(name) { _isSubscriptionAttribute = attribute => attribute is SubscriptionAttribute; _hasSubscriptionAttribute = mi => mi.GetCustomAttributes(false).Any(_isSubscriptionAttribute); InvokeCommand = new DelegateCommand(param =>{ InvokeFunction(param.Split(',')); }, functionName => { return true; }); DeviceCommand = new DelegateCommand(operation => { string[] args = operation.Split(','); DeviceFunction(args[0], args[1]); }, functionName => { return true; }); DeviceControlCommand = new DelegateCommand(args => { DeviceControlFunction((object[])args); }, functionName => { return true; }); TraverseKeys(); } public static string UIKey(string param1, string param2) { return param1 + "." + param2; } public static string UIKey(string param1, string param2, string param3) { return param1 + "." + param2 + "."+param3; } public static string UIKey(string param1, string param2, string param3, string param4) { return param1 + "." + param2 + "." + param3 + "."+param4; } protected override void Poll() { if (PollDataFunction != null && _subscribedKeys.Count > 0) { Dictionary result = PollDataFunction(_subscribedKeys); if (result == null) { LOG.Error("获取RT数据失败"); return; } if (result.Count != _subscribedKeys.Count) { string unknowKeys = string.Empty; foreach (string key in _subscribedKeys) { if (!result.ContainsKey(key)) { unknowKeys += key + "\r\n"; } } //if (unknowKeys.Length > 0) // LOG.Error("UI did not get data element:" + unknowKeys); } InvokeBeforeUpdateProperty(result); UpdateValue(result); } } protected virtual void InvokeBeforeUpdateProperty(Dictionary data) { } void UpdateValue(Dictionary data) { if (data == null) return; Parallel.ForEach(this.GetType().GetProperties().Where(_hasSubscriptionAttribute), property => { PropertyInfo pi = (PropertyInfo)property; SubscriptionAttribute subscription = property.GetCustomAttributes(false).First(_isSubscriptionAttribute) as SubscriptionAttribute; string key = subscription.ModuleKey; if (_subscribedKeys.Contains(key) && data.ContainsKey(key)) { try { var convertedValue = Convert.ChangeType(data[key], pi.PropertyType); var originValue = Convert.ChangeType(pi.GetValue(this, null), pi.PropertyType); if (originValue != convertedValue) { if (pi.Name == "PumpLimitSetPoint") pi.SetValue(this, convertedValue, null); else pi.SetValue(this, convertedValue, null); } } catch (Exception ex) { LOG.Error("由RT返回的数据更新失败" + key, ex); } } }); Parallel.ForEach(this.GetType().GetFields().Where(_hasSubscriptionAttribute), property => { FieldInfo pi = (FieldInfo)property; SubscriptionAttribute subscription = property.GetCustomAttributes(false).First(_isSubscriptionAttribute) as SubscriptionAttribute; string key = subscription.ModuleKey; if (_subscribedKeys.Contains(key) && data.ContainsKey(key)) { try { var convertedValue = Convert.ChangeType(data[key], pi.FieldType); pi.SetValue(this, convertedValue); } catch (Exception ex) { LOG.Error("由RT返回的数据更新失败" + key, ex); } } }); } void TraverseKeys() { Parallel.ForEach(this.GetType().GetProperties().Where(_hasSubscriptionAttribute), property => { SubscriptionAttribute subscription = property.GetCustomAttributes(false).First(_isSubscriptionAttribute) as SubscriptionAttribute; string key = subscription.ModuleKey; if (!_subscribedKeys.Contains(key)) _subscribedKeys.Add(key); }); Parallel.ForEach(this.GetType().GetFields().Where(_hasSubscriptionAttribute), method => { SubscriptionAttribute subscription = method.GetCustomAttributes(false).First(_isSubscriptionAttribute) as SubscriptionAttribute; string key = subscription.ModuleKey; if (!_subscribedKeys.Contains(key)) _subscribedKeys.Add(key); }); } void Subscribe(Binding binding, string bindingPathName) { if (binding != null) { string path = binding.Path.Path; if (path.Contains(bindingPathName) && path.Contains('[') && path.Contains(']')) { try { Subscribe(path.Substring(path.IndexOf('[') + 1, path.IndexOf(']') - path.IndexOf('[') - 1)); } catch (Exception ex) { LOG.Write(ex); } } } } protected void Subscribe(string key) { if (!string.IsNullOrEmpty(key) ) { _subscribedKeys.Add(key); } } protected void Subscribe(string key, object value) { if (!string.IsNullOrEmpty(key) ) { _subscribedKeys.Add(key); } } } }