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
}
}