using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Reflection; namespace FObjBase.Reflect { /// <summary> /// obj 服务代理; /// 1.如果代理的对象为 INotifyPropertyChanged, 对象内的 property 改变,能推送给客户端( [JsonIgnore] 除外); /// 2.代理的对象不为INotifyPropertyChanged, 但 对象内的 property /// a.是 [PropertyPush], /// b.且是 INotifyPropertyChanged, /// c.且 只能是get,不能有set, /// 那这个 property 内的 子property 改变,也会推送给 客户端 且 子property 是 [PropertyPush],会继续向下全部注册 PropertyChanged, /// 也推送给 客户端; /// 3. 客户端 可以通过 Call(.....) 调用 服务 的function, function返回的内容,需要通过[Call(...)] 定义; 且function 必须是 /// void function(object param1, object param2,object paramN, AsyncCBHandler asyncDelegate, object asyncContext); /// 必须有参数 AsyncCBHandler asyncDelegate, object asyncContext, 名字不能改。 前面的 param1~paramN, 多少个都行 /// 4. 服务中的event, 通过 [Push(...)] 可以推送给客户端, 但event 只能是 EventHandler /// [Push(typeof(BulkDBTempFrameChangedEventArgs))] /// public event EventHandler TempFrameChanged; /// /// </summary> public class Reflect_Proxy : FObj { #region Core /// <summary> /// 对象的接口类型 /// </summary> Type interfaceType; /// <summary> /// 代理对象 /// </summary> object obj; /// <summary> /// 忽略设置 /// </summary> public bool ignoreSet = false; /// <summary> /// 对象的全部event /// </summary> List<AnyEvent> anyEvents = new List<AnyEvent>(); /// <summary> /// [PropertyPush] 标签树 /// </summary> SubPropertyNode rootNode; /// <summary> /// interfaceType 及其父类 的全部属性 /// </summary> List<string> properties = new List<string>(); #endregion public Reflect_Proxy(int objsys_idx, UInt32 id, Type interfaceType, object obj) : base(objsys_idx) { ID = id; Init(interfaceType, obj); } #region Core public void Init(Type interfaceType, object obj) { this.interfaceType = interfaceType; this.obj = obj; rootNode = new SubPropertyNode { Obj = obj, InterfaceType = interfaceType, SubPropertyChanged = Sub_PropertyChanged }; //注册 obj 的PropertyChanged 事件,获取 interfaceType 全部属性名称,包括它的父类的全部属性名称 InitPropertyChanged(); //处理[PropertyPush] COMMON.InitPropertyPush(rootNode); //处理[Push] InitEventPush(); } void InitPropertyChanged() { if (!typeof(INotifyPropertyChanged).IsAssignableFrom(interfaceType)) return; //继承了INotifyPropertyChanged ((INotifyPropertyChanged)(this.obj)).PropertyChanged += rootNode.PropertyChanged; var propertyInfos = COMMON.GetAllPropertyInfos(this.interfaceType);//获取全部属性, 包括父类的属性 foreach (var propertyInfo in propertyInfos) { if (propertyInfo.GetCustomAttribute<JsonIgnoreAttribute>() != null) continue;//这个不需要推送 if (properties.Contains(propertyInfo.Name)) continue; properties.Add(propertyInfo.Name); } } void InitEventPush() { var interfaceTypes = new List<Type>(); interfaceTypes.Add(this.interfaceType); interfaceTypes.AddRange(this.interfaceType.GetInterfaces()); var eventInfos = new List<EventInfo>(); foreach (var ifaceType in interfaceTypes) { eventInfos.AddRange(ifaceType.GetEvents()); } foreach (var eventInfo in eventInfos) { var pushAttribute = eventInfo.GetCustomAttribute<PushAttribute>(); if (pushAttribute == null) continue; if (anyEvents.Any(ae => ae.eventName == eventInfo.Name)) continue;//已经添加了 var anyEvent = new AnyEvent() { eventName = eventInfo.Name, PushObjInfoEx = (rd) => reponse_PushObjInfoEx(rd, true) }; //这个事件需要推送 eventInfo.AddEventHandler(obj, anyEvent.eventHandler); anyEvents.Add(anyEvent); } } void Sub_PropertyChanged(SubPropertyNode node, PropertyChangedEventArgs e) { //if (ignoreSet)//从服务器接收的数据,不用再推送给服务器 // return; var type = node.Obj.GetType(); var propertyInfo = type.GetProperty(e.PropertyName); if (propertyInfo == null) return;//获取失败!!! if (propertyInfo.GetCustomAttribute<JsonIgnoreAttribute>() != 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 }; reponse_PushObjInfoEx(rData, false); } Reflect_OBJ_INTERFACE.ReflectData request_CALL_GetAllProperties() { var jObject = new JObject(); var type = obj.GetType(); foreach (var propertyName in properties) { var propertyInfo = type.GetProperty(propertyName); var v = propertyInfo.GetValue(obj); if (v == null) jObject.Add(propertyInfo.Name, null); else jObject.Add(propertyInfo.Name, JToken.FromObject(v)); } var rData = new Reflect_OBJ_INTERFACE.ReflectData { data = jObject }; return rData; } void request_CALL_SetProperty(Reflect_OBJ_INTERFACE.ReflectData rData) { //ignoreSet = true; //sub property var node = COMMON.FindNode(rootNode, rData.name); if (node == null) { //异常 //客户端乱发过来 return; } string json = rData.data.ToString(); JsonConvert.PopulateObject(json, node.Obj); //ignoreSet = false; } void request_CALL_MethodInvoke(Reflect_OBJ_INTERFACE.ReflectData rData, CC cc) { var type = obj.GetType(); var paramNames_req = rData.data.Children().OfType<JProperty>().Select(p => p.Name); MethodInfo methodInfo = GetMethodInfo(type, rData.name, paramNames_req); if (methodInfo == null) { //不能找到, throw new Exception($"程序写错了, 不能找到 rData.name={rData.name} 或者 参数名称不对,没法完全匹配"); } var parameterInfos = methodInfo.GetParameters(); object[] parameters = new object[parameterInfos.Count()]; for (int i = 0; i < parameters.Count(); i++) { var ptype = parameterInfos[i].ParameterType; var pname = parameterInfos[i].Name; if (string.Compare(pname, Reflect_OBJ_INTERFACE.asyncDelegate, true) == 0) { parameters[i] = new AsyncCBHandler(asyncDelegate); } else if (string.Compare(pname, Reflect_OBJ_INTERFACE.asyncContext, true) == 0) { cc.methodName = rData.name; parameters[i] = cc; } else { parameters[i] = rData.data[pname].ToObject(ptype); } } methodInfo.Invoke(obj, parameters); } void asyncDelegate(object asyncContext, object retData) { var cc = (CC)asyncContext; var rData = new Reflect_OBJ_INTERFACE.ReflectData() { name = cc.methodName, data = retData == null ? null : JToken.FromObject(retData) }; reponse_CALL_MethodInvoke(rData, cc); } MethodInfo GetMethodInfo(Type type, string name, IEnumerable<string> parameterNames) { var methodInfos = from mi in type.GetMethods() where mi.Name == name select mi; if (methodInfos.Count() == 0) return null; if (methodInfos.Count() == 1) return methodInfos.First(); //必须完全匹配 foreach (var methodInfo in methodInfos) { var parameterInfos = methodInfo.GetParameters(); //全部参数名称 var names = parameterInfos.Select(pi => pi.Name).ToList(); //删除掉 asyncDelegate,asyncContext names.Remove(Reflect_OBJ_INTERFACE.asyncDelegate); names.Remove(Reflect_OBJ_INTERFACE.asyncContext); var names_req = parameterNames; if (names.Count() != names_req.Count()) continue;//数量不一致,肯定不同 var sames = names_req.Intersect(names); if (sames.Count() != names_req.Count()) continue;// names 与 names_req 的交集数量与names_req不一样,肯定不同 //就是它 return methodInfo; } return null; } public void Dispose() { if (typeof(INotifyPropertyChanged).IsAssignableFrom(interfaceType)) { //继承了INotifyPropertyChanged ((INotifyPropertyChanged)(this.obj)).PropertyChanged -= rootNode.PropertyChanged; } //释放subProperties COMMON.NodeDispose(rootNode); } #endregion void reponse_PushObjInfoEx(Reflect_OBJ_INTERFACE.ReflectData rData, bool isEvent) { //数据推送!!! //再嵌套 var pkgName = isEvent ? Reflect_OBJ_INTERFACE.PUSH_Event : Reflect_OBJ_INTERFACE.PUSH_PropertyChanged; string json = JsonConvert.SerializeObject(rData); CurrObjSys.PushObjInfoEx(this, pkgName, Misc.Converter.StringToBytes(json)); } void reponse_CALL_MethodInvoke(Reflect_OBJ_INTERFACE.ReflectData rData, CC cc) { string json = JsonConvert.SerializeObject(rData); CurrObjSys.PushCallFunctionEx( cc.from, cc.srcid, ID, cc.magic, Reflect_OBJ_INTERFACE.CALL_MethodInvoke, Misc.Converter.StringToBytes(json)); } void reponse_CALL_GetAllProperties(Reflect_OBJ_INTERFACE.ReflectData rData, CC cc) { string json = JsonConvert.SerializeObject(rData); CurrObjSys.PushCallFunctionEx( cc.from, cc.srcid, ID, cc.magic, Reflect_OBJ_INTERFACE.CALL_GetAllProperties, Misc.Converter.StringToBytes(json)); } public override void CallFunction(IFConn from, uint srcid, uint magic, ushort funcid, byte[] infodata) { switch (funcid) { case Reflect_OBJ_INTERFACE.CALL_GetAllProperties: { var rData = request_CALL_GetAllProperties(); reponse_CALL_GetAllProperties(rData, new CC() { from = from, srcid = srcid, magic = magic }); } break; case Reflect_OBJ_INTERFACE.CALL_SetProperty: { string json = Misc.Converter.BytesToString(infodata); var rData = JsonConvert.DeserializeObject<Reflect_OBJ_INTERFACE.ReflectData>(json); request_CALL_SetProperty(rData); } break; case Reflect_OBJ_INTERFACE.CALL_MethodInvoke: { string json = Misc.Converter.BytesToString(infodata); var rData = JsonConvert.DeserializeObject<Reflect_OBJ_INTERFACE.ReflectData>(json); request_CALL_MethodInvoke(rData, new CC() { from = from, srcid = srcid, magic = magic }); } break; } } class CC { public IFConn from; public UInt32 srcid; public UInt32 magic; /// <summary> /// CALL_MethodInvoke 时使用 /// </summary> public string methodName; } } /// <summary> /// 事件推送包装 /// </summary> class AnyEvent { /// <summary> /// 事件名称 /// </summary> public string eventName; /// <summary> /// json包装后的ReflectData 推送 /// </summary> public Action<Reflect_OBJ_INTERFACE.ReflectData> PushObjInfoEx; /// <summary> /// 给 EventInfo 调用 /// </summary> public EventHandler eventHandler; public AnyEvent() { eventHandler = new EventHandler(Obj_AnyEvent); } void Obj_AnyEvent(object sender, EventArgs e) { var rData = new Reflect_OBJ_INTERFACE.ReflectData() { name = eventName, data = JObject.FromObject(e) }; PushObjInfoEx?.Invoke(rData); } } }