/// <summary> /// Invokes a method remotely, and returns the result /// </summary> /// <returns>The result of the remote invocation.</returns> /// <param name="handle">The remote instance handle, or zero for null.</param> /// <param name="remotetype">A type descriptor for the type the method is invoked on.</param> /// <param name="remotemethod">A serialized description of the method to invoke.</param> /// <param name="types">The types of the input arguments.</param> /// <param name="arguments">The values given to the method when invoked.</param> /// <param name="isWrite">If set to <c>true</c> this is a write field or property request.</param> public async Task <object> InvokeRemoteMethodAsync(long handle, string remotetype, string remotemethod, Type[] types, object[] arguments, bool isWrite) { if (string.IsNullOrWhiteSpace(remotetype)) { throw new ArgumentNullException(remotetype); } if (string.IsNullOrWhiteSpace(remotemethod)) { throw new ArgumentNullException(remotemethod); } types = types ?? new Type[0]; arguments = arguments ?? new object[0]; if (types.Length != arguments.Length) { throw new ArgumentOutOfRangeException(nameof(types), $"The length of {nameof(types)} must be the same as the length of {nameof(arguments)}"); } // Register each local reference item with the remote for (var i = 0; i < arguments.Length; i++) { var arg = arguments[i]; if (arg == null) { continue; } var tp = arg.GetType(); var action = m_typeSerializer.GetAction(tp); if (action == SerializationAction.Fail) { var ta = m_typeSerializer.GetAction(types[i]); if (ta != SerializationAction.Fail) { action = ta; tp = types[i]; } } if (action == SerializationAction.Fail) { throw new Exception($"Cannot pass item with type {arg.GetType()} ({types[i]})"); } if (m_preSendHooks.Count > 0) { await Task.WhenAll(m_preSendHooks.Select(x => x(arg, tp))); } if (action == SerializationAction.Reference || m_remoteObjects.IsLocalObject(arg)) { await RegisterLocalObjectOnRemote(arg, tp); } } var res = await m_connection.SendAndWaitAsync( Command.InvokeRemoteMethod, new InvokeRemoteMethodRequest(handle, remotetype, remotemethod, isWrite, types, arguments) ); if (res.Types.Length == 0 || res.Types[0] == typeof(void)) { return(null); } var resp = (InvokeRemoteMethodResponse)res.Values[0]; if (resp.ResultType == typeof(void) || resp.ResultType == typeof(Task)) { return(null); } if (resp.ResultType.IsConstructedGenericType && resp.ResultType.GetGenericTypeDefinition() == typeof(Task <>)) { return(resp.Result); } return(resp.Result); }