コード例 #1
0
ファイル: HubDispatcher.cs プロジェクト: shinedownn/SignalR
        /// <summary>
        /// Processes the hub's incoming method calls.
        /// </summary>
        protected override Task OnReceivedAsync(IRequest request, string connectionId, string data)
        {
            HubRequest hubRequest = _requestParser.Parse(data);

            // Create the hub
            HubDescriptor descriptor = _manager.EnsureHub(hubRequest.Hub,
                                                          _hubResolutionErrorsTotalCounter,
                                                          _hubResolutionErrorsPerSecCounter,
                                                          _allErrorsTotalCounter,
                                                          _allErrorsPerSecCounter);

            IJsonValue[] parameterValues = hubRequest.ParameterValues;

            // Resolve the method
            MethodDescriptor methodDescriptor = _manager.GetHubMethod(descriptor.Name, hubRequest.Method, parameterValues);

            if (methodDescriptor == null)
            {
                _hubResolutionErrorsTotalCounter.SafeIncrement();
                _hubResolutionErrorsPerSecCounter.SafeIncrement();
                throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, "'{0}' method could not be resolved.", hubRequest.Method));
            }

            // Resolving the actual state object
            var state = new TrackingDictionary(hubRequest.State);
            var hub   = CreateHub(request, descriptor, connectionId, state, throwIfFailedToCreate: true);

            Task resultTask;

            try
            {
                // Invoke the method
                object result     = methodDescriptor.Invoker.Invoke(hub, _binder.ResolveMethodParameters(methodDescriptor, parameterValues));
                Type   returnType = result != null?result.GetType() : methodDescriptor.ReturnType;

                if (typeof(Task).IsAssignableFrom(returnType))
                {
                    var task = (Task)result;
                    if (!returnType.IsGenericType)
                    {
                        return(task.ContinueWith(t => ProcessResponse(state, null, hubRequest, t.Exception))
                               .FastUnwrap());
                    }
                    else
                    {
                        // Get the <T> in Task<T>
                        Type resultType = returnType.GetGenericArguments().Single();

                        // Get the correct ContinueWith overload
                        var continueWith = TaskAsyncHelper.GetContinueWith(task.GetType());

                        var taskParameter       = Expression.Parameter(continueWith.Type);
                        var processResultMethod = typeof(HubDispatcher).GetMethod("ProcessTaskResult", BindingFlags.NonPublic | BindingFlags.Instance).MakeGenericMethod(resultType);

                        var body = Expression.Call(Expression.Constant(this),
                                                   processResultMethod,
                                                   Expression.Constant(state),
                                                   Expression.Constant(hubRequest),
                                                   taskParameter);

                        var lambda = Expression.Lambda(body, taskParameter);

                        var call = Expression.Call(Expression.Constant(task, continueWith.Type), continueWith.Method, lambda);
                        Func <Task <Task> > continueWithMethod = Expression.Lambda <Func <Task <Task> > >(call).Compile();
                        return(continueWithMethod.Invoke().FastUnwrap());
                    }
                }
                else
                {
                    resultTask = ProcessResponse(state, result, hubRequest, null);
                }
            }
            catch (TargetInvocationException e)
            {
                resultTask = ProcessResponse(state, null, hubRequest, e);
            }

            return(resultTask.Then(() => base.OnReceivedAsync(request, connectionId, data))
                   .Catch());
        }
コード例 #2
0
        protected override Task OnReceivedAsync(string connectionId, string data)
        {
            var hubRequest = _serializer.Deserialize <HubRequest>(data);

            // Create the hub
            IHub hub = _hubFactory.CreateHub(hubRequest.Hub);

            // Deserialize the parameter name value pairs so we can match it up with the method's parameters
            var parameters = hubRequest.Data;

            // Resolve the action
            ActionInfo actionInfo = _actionResolver.ResolveAction(hub.GetType(), hubRequest.Action, parameters);

            if (actionInfo == null)
            {
                throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, "'{0}' could not be resolved.", hubRequest.Action));
            }

            string hubName = hub.GetType().FullName;

            var state = new TrackingDictionary(hubRequest.State);

            hub.Context = new HubContext(connectionId, _cookies, _user);
            hub.Caller  = new SignalAgent(Connection, connectionId, hubName, state);
            var agent = new ClientAgent(Connection, hubName);

            hub.Agent        = agent;
            hub.GroupManager = agent;
            Task resultTask;

            try
            {
                // Execute the method
                object result     = actionInfo.Method.Invoke(hub, actionInfo.Arguments);
                Type   returnType = result != null?result.GetType() : actionInfo.Method.ReturnType;

                if (typeof(Task).IsAssignableFrom(returnType))
                {
                    var task = (Task)result;
                    if (!returnType.IsGenericType)
                    {
                        return(task.ContinueWith(t => ProcessResult(state, null, hubRequest, t.Exception))
                               .FastUnwrap());
                    }
                    else
                    {
                        // Get the <T> in Task<T>
                        Type resultType = returnType.GetGenericArguments().Single();

                        // Get the correct ContinueWith overload
                        var continueWith = TaskAsyncHelper.GetContinueWith(task.GetType());

                        var taskParameter       = Expression.Parameter(continueWith.Type);
                        var processResultMethod = typeof(HubDispatcher).GetMethod("ProcessResult", BindingFlags.NonPublic | BindingFlags.Instance);
                        var taskResult          = Expression.Property(taskParameter, "Result");
                        var taskException       = Expression.Property(taskParameter, "Exception");

                        var body = Expression.Call(Expression.Constant(this),
                                                   processResultMethod,
                                                   Expression.Constant(state),
                                                   Expression.Convert(taskResult, typeof(object)),
                                                   Expression.Constant(hubRequest),
                                                   Expression.Convert(taskException, typeof(Exception)));

                        var lambda = Expression.Lambda(body, taskParameter);

                        var call = Expression.Call(Expression.Constant(task, continueWith.Type), continueWith.Method, lambda);
                        return(Expression.Lambda <Func <Task <Task> > >(call).Compile()().FastUnwrap());
                    }
                }
                else
                {
                    resultTask = ProcessResult(state, result, hubRequest, null);
                }
            }
            catch (TargetInvocationException e)
            {
                resultTask = ProcessResult(state, null, hubRequest, e);
            }

            return(resultTask
                   .ContinueWith(_ => base.OnReceivedAsync(connectionId, data))
                   .FastUnwrap());
        }