bool Invoke <T>(AADCommand command, ISerializable parameters, [NotNullWhen(true)] out T?result) where T : class, ISerializable { result = null; if (!IsConnected) { return(false); } var r = InvokeOne(command, parameters, out var result2); Debug2.Assert(r != ExecutionResult.UnknownCommand); // internal error, we should fix it switch (r) { case ExecutionResult.IOError: case ExecutionResult.Disconnect: Disconnect(); return(false); case ExecutionResult.Success: result = result2 as T; return(result is not null); default: return(false); } }
/// <summary> /// Read command from stream /// </summary> /// <param name="command"></param> /// <param name="throwing"></param> /// <returns></returns> /// <exception cref="IOException"></exception> internal bool ReadCommand(out AADCommand command, bool throwing = true) { command = AADCommand.Invalid; var buffer = new byte[4]; if (!Read(buffer, throwing)) { return(false); } command = (AADCommand)BitConverter.ToUInt32(buffer, 0); return(true); }
/// <summary> /// Invoke one specified command with parameters /// </summary> /// <param name="command"></param> /// <param name="parameters"></param> /// <param name="result"></param> /// <returns></returns> /// <remarks>See executor: <seealso cref="AADServer.ExecuteOne"/></remarks> ExecutionResult InvokeOne(AADCommand command, ISerializable parameters, out ISerializable?result) { result = null; try { if (!CommandHandlerManager.Handlers.TryGetValue(command, out var handler)) { Debug2.Assert(false); return(ExecutionResult.UnknownCommand); } // phase 1: get the handler corresponding to the command WriteCommand(command); Write(parameters); // phase 2: write parameters to stream ReadCommand(out var resultCommand); if (resultCommand == AADCommand.UnhandledException) { var exception = new AADServerInvocationException(); Read(exception); throw exception; } if (resultCommand != AADCommand.Success) { return(ExecutionResult.Failure); } // phase 3: read execution result result = Activator.CreateInstance(handler.ResultType, true) as ISerializable; if (result is null) { throw new InvalidOperationException("Can't create result object"); } // phase 4: create result instance Read(result); // phase 5: read result from stream return(ExecutionResult.Success); } catch (AADServerInvocationException) { throw; } catch (Exception ex) { Debug2.Assert(ex is IOException); // regard all unhandable exceptions as IO error return(ExecutionResult.IOError); } }
/// <summary> /// Write command to stream /// </summary> /// <param name="command"></param> /// <returns></returns> /// <exception cref="IOException"></exception> internal bool WriteCommand(AADCommand command, bool throwing = true) { var buffer = BitConverter.GetBytes((uint)command); return(Write(buffer, throwing)); }