Exemplo n.º 1
0
        /// <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);
        }