using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace FObjBase.Reflect { public abstract class Reflect_SeviceClient : FObjServiceClient { #region Core /// /// 忽略设置 /// public bool ignoreSet; /// /// 代理对象 接口类型 /// protected abstract Type InterfaceType { get; } /// /// 已经同步完成; /// 已经收到了 CALL_GetAllProperties, 全部属性都与服务器一致 /// public bool IsSynced { get; private set; } /// /// 当前 INotifyPropertyChanged 对象 引发了 PropertyChanged, 是由于 接收到数据导致的 /// public bool IsInPushValue { get; protected set; } class AnyEvent { public string name; public string triggerName; public Type retType; } class AnyCall { public string name; public Type retType; } List anyEvents = new List(); List anyCalls = new List(); SubPropertyNode rootNode; List properties = new List(); /// /// 缓存 发出 CALL_GetAllProperties指令,到收到回复 之间时段的 全部推送 /// List pushInfoList = new List(); class PushInfoData { public bool isPushPropertyChanged; public Reflect_OBJ_INTERFACE.ReflectData rData; } #endregion public Reflect_SeviceClient(UInt32 id) : base(id) { init(); } public Reflect_SeviceClient(UInt32 serviceId, string connName) : base(serviceId, connName) { init(); } #region Core void init() { rootNode = new SubPropertyNode { Obj = this, InterfaceType = InterfaceType, SubPropertyChanged = Sub_PropertyChanged }; InitPropertyChanged(); COMMON.InitPropertyPush(rootNode); InitEventPush(); InitCall(); this.PropertyChanged += (s, e) => { if (e.PropertyName == nameof(IsConnected)) { if (IsConnected == false) { IsSynced = false; pushInfoList.Clear(); } } }; } void InitPropertyChanged() { if (!typeof(INotifyPropertyChanged).IsAssignableFrom(InterfaceType)) return; //继承了INotifyPropertyChanged this.PropertyChanged += rootNode.PropertyChanged; var propertyInfos = COMMON.GetAllPropertyInfos(this.InterfaceType);//获取全部属性, 包括父类的属性 foreach (var propertyInfo in propertyInfos) { if (propertyInfo.GetCustomAttribute() != null) continue;//这个不需要推送 if (properties.Contains(propertyInfo.Name)) continue; properties.Add(propertyInfo.Name); } } void InitEventPush() { var interfaceTypes = new List(); interfaceTypes.Add(InterfaceType); interfaceTypes.AddRange(InterfaceType.GetInterfaces()); var eventInfos = new List(); foreach (var ifaceType in interfaceTypes) { eventInfos.AddRange(ifaceType.GetEvents()); } foreach (var eventInfo in eventInfos) { var pushAttribute = eventInfo.GetCustomAttribute(); if (pushAttribute == null) continue; if (anyEvents.Any(ae => ae.name == eventInfo.Name)) continue;//已经添加了 string triggerName; if (string.IsNullOrEmpty(pushAttribute.TriggerName)) { triggerName = PushAttribute.DefaultTriggerNameHeader + eventInfo.Name; } else { triggerName = pushAttribute.TriggerName; } var anyEvent = new AnyEvent() { name = eventInfo.Name, triggerName = triggerName, retType = pushAttribute.EventArgsType }; anyEvents.Add(anyEvent); } } void InitCall() { var interfaceTypes = new List(); interfaceTypes.Add(InterfaceType); interfaceTypes.AddRange(InterfaceType.GetInterfaces()); var methodInfos = new List(); foreach (var ifaceType in interfaceTypes) { methodInfos.AddRange(ifaceType.GetMethods()); } foreach (var methodInfo in methodInfos) { var callAttribute = methodInfo.GetCustomAttribute(); if (callAttribute == null) continue; if (anyCalls.Any(ae => ae.name == methodInfo.Name)) continue;//已经添加了 var anyCall = new AnyCall() { name = methodInfo.Name, retType = callAttribute.ReponseType }; anyCalls.Add(anyCall); } } private void Sub_PropertyChanged(SubPropertyNode node, PropertyChangedEventArgs e) { if (!IsConnected) return; if (ignoreSet)//从服务器接收的数据,不用再推送给服务器 return; var type = node.Obj.GetType(); var propertyInfo = type.GetProperty(e.PropertyName); if (propertyInfo == null) return;//获取失败!!! if (propertyInfo.GetCustomAttribute() != null) return;//这个不需要推送 var v = propertyInfo.GetValue(node.Obj); var jObject = new JObject(); if (v == null) jObject.Add(propertyInfo.Name, null); else jObject.Add(propertyInfo.Name, JToken.FromObject(v)); var rData = new Reflect_OBJ_INTERFACE.ReflectData { name = COMMON.GetNodePath(node), data = jObject }; send_CALL_SetProperty(rData); } public override void Dispose() { base.Dispose(); if (typeof(INotifyPropertyChanged).IsAssignableFrom(InterfaceType)) { //继承了INotifyPropertyChanged ((INotifyPropertyChanged)(this)).PropertyChanged -= rootNode.PropertyChanged; } //释放subProperties COMMON.NodeDispose(rootNode); } protected void Call(string methodName, object parameters, AsyncCBHandler asyncDelegate, object asyncContext) { var rData = new Reflect_OBJ_INTERFACE.ReflectData() { name = methodName, data = parameters == null ? null : JObject.FromObject(parameters) }; send_CALL_MethodInvoke(rData, asyncDelegate, asyncContext); } protected void Call(string methodName, object parameters) { Call(methodName, parameters, null, null); } protected void Call(string methodName) { Call(methodName, null, null, null); } /// /// 处理 从服务器 回复的 CALL_GetAllProperties /// /// void receive_CALL_GetAllProperties(Reflect_OBJ_INTERFACE.ReflectData rData) { receive_PUSH_PropertyChanged(rData); IsSynced = true; DealPushInfoList(); } /// /// 处理全部 缓存的推送数据 /// void DealPushInfoList() { for (int i = 0; i < pushInfoList.Count(); i++) { var pushInfoData = pushInfoList[i]; if (pushInfoData.isPushPropertyChanged) receive_PUSH_PropertyChanged(pushInfoData.rData); else receive_PUSH_Event(pushInfoData.rData); } pushInfoList.Clear(); } /// /// 处理 从服务器 回复的 PUSH_PropertyChanged /// /// void receive_PUSH_PropertyChanged(Reflect_OBJ_INTERFACE.ReflectData rData) { ignoreSet = true; IsInPushValue = true; var node = COMMON.FindNode(rootNode, rData.name); if (node == null) { //异常 //服务器乱发过来 return; } string json = rData.data.ToString(); JsonConvert.PopulateObject(json, node.Obj); IsInPushValue = false; ignoreSet = false; } /// /// 处理 从服务器 回复的 PUSH_Event /// /// void receive_PUSH_Event(Reflect_OBJ_INTERFACE.ReflectData rData) { if (InterfaceType == null) return; var anyEvent = anyEvents.Find(ae => ae.name == rData.name); if (anyEvent == null) return;//异常!!! //触发事件!!! var methodInfo = GetType().GetMethod(anyEvent.triggerName); if (methodInfo == null) { throw new Exception($"客户端 {GetType()} 忘记写 {anyEvent.triggerName}"); } var obj = rData.data.ToObject(anyEvent.retType); //出错,就提示,肯定是客户端忘记写 "Trigger_XXXX" methodInfo.Invoke(this, new object[] { obj }); } /// /// 处理 从服务器 回复的 CALL_MethodInvoke /// /// /// /// void receive_CALL_MethodInvoke(Reflect_OBJ_INTERFACE.ReflectData rData, AsyncCBHandler asyncDelegate, object asyncContext) { var anyCall = anyCalls.Find(ac => ac.name == rData.name); if (anyCall == null) { //异常!!!应该有[Call]注明返回的类型 throw new Exception($"{rData.name} 异常!!!应该有[Call]注明返回的类型"); } var retData = rData.data.ToObject(anyCall.retType); asyncDelegate.Invoke(asyncContext, retData); } #endregion /// /// 发送 CALL_MethodInvoke 请求到服务器 /// /// /// /// void send_CALL_MethodInvoke(Reflect_OBJ_INTERFACE.ReflectData rData, AsyncCBHandler asyncDelegate, object asyncContext) { string json = JsonConvert.SerializeObject(rData); CurrObjSys.CallFunctionEx(mConn, mServerID, ID, Reflect_OBJ_INTERFACE.CALL_MethodInvoke, Misc.Converter.StringToBytes(json), asyncDelegate, asyncContext); } /// /// 发送 CALL_SetProperty 请求到服务器 /// /// void send_CALL_SetProperty(Reflect_OBJ_INTERFACE.ReflectData rData) { string json = JsonConvert.SerializeObject(rData); CurrObjSys.CallFunctionEx(mConn, mServerID, ID, Reflect_OBJ_INTERFACE.CALL_SetProperty, Misc.Converter.StringToBytes(json)); } #region FObj public override void ConnectNotify(IFConn from) { base.ConnectNotify(from); if (from.IsConnected) { //获取所有数据,设置推送 CurrObjSys.CallFunctionEx( mConn, mServerID, ID, Reflect_OBJ_INTERFACE.CALL_GetAllProperties, null); CurrObjSys.SenseConfigEx( mConn, mServerID, ID, 0xffffffff, SENSE_CONFIG.ADD); } } public override void PushInfo(IFConn from, uint srcid, ushort infoid, byte[] infodata) { switch (infoid) { case Reflect_OBJ_INTERFACE.PUSH_PropertyChanged: case Reflect_OBJ_INTERFACE.PUSH_Event: { string json = Misc.Converter.BytesToString(infodata); var rData = JsonConvert.DeserializeObject(json); if (!IsSynced) { //还没同步完成,先缓存 pushInfoList.Add( new PushInfoData() { isPushPropertyChanged = (infoid == Reflect_OBJ_INTERFACE.PUSH_PropertyChanged), rData = rData }); return; } if(infoid == Reflect_OBJ_INTERFACE.PUSH_PropertyChanged) receive_PUSH_PropertyChanged(rData); else receive_PUSH_Event(rData); } break; } } public override void PushCallFunction(IFConn from, uint srcid, uint magic, ushort funcid, byte[] retdata, AsyncCBHandler asyncDelegate, object asyncContext) { switch (funcid) { case Reflect_OBJ_INTERFACE.CALL_GetAllProperties: { string json = Misc.Converter.BytesToString(retdata); var rData = JsonConvert.DeserializeObject(json); receive_CALL_GetAllProperties(rData); } break; case Reflect_OBJ_INTERFACE.CALL_MethodInvoke: { if (InterfaceType == null) return; string json = Misc.Converter.BytesToString(retdata); var rData = JsonConvert.DeserializeObject(json); receive_CALL_MethodInvoke(rData, asyncDelegate, asyncContext); } break; } } #endregion } }