tesses-rpc/Tesses.RPC/Class1.cs

187 lines
6.7 KiB
C#

/*
Tesses.RPC A simple RPC library for .NET
Copyright (C) 2023 Mike Nolan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
namespace Tesses.RPC
{
public abstract class MessageHandler
{
public abstract void SendMessage(string msg);
public void OnMessageReceived(string msg)
{
MessageRecv?.Invoke(msg);
}
internal event Action<string> MessageRecv;
}
public sealed class MessageReceived<T,TType>
{
Action<TType> reply;
internal MessageReceived(T data,bool needReply,Action<TType> reply)
{
Data = data;
NeedReply = needReply;
this.reply=reply;
}
public T Data {get;private set;}
public bool NeedReply {get;private set;}
public void Reply(TType msg)
{
reply?.Invoke(msg);
}
}
public sealed class JsonMessager<TEnum,TType> where TEnum : Enum
{
Dictionary<TEnum,(Type type,Action<JsonMessage<TEnum>> resp)> items=new Dictionary<TEnum, (Type type,Action<JsonMessage<TEnum>> resp)>();
MessageHandler handler;
public JsonMessager(MessageHandler handler)
{
this.handler = handler;
this.handler.MessageRecv += message_recv;
}
private void message_recv(string msg)
{
var res= JsonConvert.DeserializeObject<JsonMessage<TEnum>>(msg);
if(res != null && items.ContainsKey(res.Type))
{
items[res.Type].resp?.Invoke(res);
}
}
private event Action<JsonMessage<TEnum>> recv_res;
public void Register<T>(TEnum val,Action<MessageReceived<T,TType>> recv) where T : TType
{
if(!items.ContainsKey(val))
{
Action<JsonMessage<TEnum>> msger= (msg)=>{
if(recv!=null && msg.MessageState != MessageState.ResponseNoForget)
{
MessageReceived<T,TType> msg0=new MessageReceived<T,TType>(msg.Value.ToObject<T>(),msg.MessageState != MessageState.Forget ,(reply)=>{
SendMessageResponse(reply,msg.Id);
});
recv?.Invoke(msg0);
}else if(msg.MessageState == MessageState.ResponseNoForget){
recv_res?.Invoke(msg);
}
};
items.Add(val,(typeof(T),msger));
}
}
private void SendMessageResponse(TType msg,long msgId)
{
foreach(var item in items)
{
if(item.Value.type == msg.GetType())
{
JsonMessage<TEnum> jsonMessage = new JsonMessage<TEnum>();
jsonMessage.Type=item.Key;
jsonMessage.Value=JToken.FromObject(msg);
jsonMessage.Id = msgId;
jsonMessage.MessageState = MessageState.ResponseNoForget;
string text=JsonConvert.SerializeObject(jsonMessage);
handler.SendMessage(text);
return;
}
}
}
public void SendMessage(TType msg)
{
foreach(var item in items)
{
if(item.Value.type == msg.GetType())
{
JsonMessage<TEnum> jsonMessage = new JsonMessage<TEnum>();
jsonMessage.Type=item.Key;
jsonMessage.Value=JToken.FromObject(msg);
jsonMessage.Id = JsonMessage<TEnum>.GetNewId();
jsonMessage.MessageState = MessageState.Forget;
string text=JsonConvert.SerializeObject(jsonMessage);
handler.SendMessage(text);
return;
}
}
}
public void SendMessage<TResponse>(TType msg,Action<TResponse> resp) where TResponse : TType
{
foreach(var item in items)
{
if(item.Value.type == msg.GetType())
{
JsonMessage<TEnum> jsonMessage = new JsonMessage<TEnum>();
jsonMessage.Type=item.Key;
jsonMessage.Value=JToken.FromObject(msg);
jsonMessage.Id = JsonMessage<TEnum>.GetNewId();
jsonMessage.MessageState = MessageState.RequestNoForget;
string text=JsonConvert.SerializeObject(jsonMessage);
recv_res += (e)=>{
if(e.Id == jsonMessage.Id && e.MessageState == MessageState.ResponseNoForget)
{
if(items.ContainsKey(e.Type) && items[e.Type].type == typeof(TResponse))
{
resp?.Invoke(e.Value.ToObject<TResponse>());
}
}
};
handler.SendMessage(text);
return;
}
}
}
internal enum MessageState
{
Forget=0,
RequestNoForget=1,
ResponseNoForget=2
}
private class JsonMessage<TEnum2> where TEnum2 : Enum
{
private static long _curId=0;
internal static long GetNewId()
{
return _curId++;
}
[JsonConverter(typeof(StringEnumConverter))]
public TEnum2 Type {get;set;}
public JToken Value {get;set;}
public long Id {get;set;}
public MessageState MessageState {get;set;}
}
}
}