RpcServer.cs
using System.Text.Json;
using System.Threading.Tasks;
namespace Extend.Callbacks;
/// <summary>
/// RPC server methods
/// </summary>
public static class RpcServer
{
/// <summary>
/// Sends an RPC message to the client.
/// This method is tagged with the <see cref="Rpc.Host"/> attribute, which means it will be executed on the server and callable by clients.
/// </summary>
/// <param name="request">The RPC message to send.</param>
/// <param name="args">The arguments to pass to the RPC method.</param>
[Rpc.Host]
public static async void SendRpc( RpcMessage request, params object[] args )
{
try
{
if ( !RpcCallbackSystem.Current.Handlers.TryGetValue( request.MethodIdent, out var handler ) )
{
var error = RpcError.CallbackNotFound( request.MethodIdent );
using ( Rpc.FilterInclude( Rpc.Caller ) )
RpcClient.OnRpcError( request.Id, error, request.MethodIdent );
return;
}
var taskResult = handler.Method.InvokeWithReturn<Task>( handler.Instance, args );
await taskResult;
var json = Json.Serialize( taskResult );
var dict = Json.Deserialize<Dictionary<string, JsonElement>>( json ).GetValueOrDefault( "Result" );
var returnType = TypeLibrary.GetTypeByIdent( request.MethodReturnTypeIdent );
var returnTargetType = returnType.TargetType;
object? finalResult;
if ( returnType.IsGenericType )
{
var genericTypes = request.GenericArguments.Select( x => TypeLibrary.GetType( x ).TargetType ).ToArray();
var baseGenericType = returnType.MakeGenericType( genericTypes );
finalResult = dict.Deserialize( baseGenericType );
}
else
{
finalResult = dict.Deserialize( returnTargetType );
}
using ( Rpc.FilterInclude( Rpc.Caller ) )
RpcClient.OnRpcResponse( request, finalResult, request.MethodIdent );
}
catch ( Exception e )
{
var error = RpcError.Unknown( request.MethodIdent, e );
Log.Error( $"RPC execution error for {request.MethodIdent}: {e}" );
using ( Rpc.FilterInclude( Rpc.Caller ) )
RpcClient.OnRpcError( request.Id, error, request.MethodIdent );
}
}
}