private Task InvokeHubPipeline(IHub hub, IJsonValue[] parameterValues, MethodDescriptor methodDescriptor, HubRequest hubRequest, StateChangeTracker tracker) { // TODO: Make adding parameters here pluggable? IValueProvider? ;) HubInvocationProgress progress = GetProgressInstance(methodDescriptor, value => SendProgressUpdate(hub.Context.ConnectionId, tracker, value, hubRequest), Logger); Task <object> piplineInvocation; try { var args = _binder.ResolveMethodParameters(methodDescriptor, parameterValues); // We need to add the IProgress<T> instance after resolving the method as the resolution // itself looks for overload matches based on the incoming arg values if (progress != null) { args = args.Concat(new[] { progress }).ToList(); } var context = new HubInvokerContext(hub, tracker, methodDescriptor, args); // Invoke the pipeline and save the task piplineInvocation = _pipelineInvoker.Invoke(context); } catch (Exception ex) { piplineInvocation = TaskAsyncHelper.FromError <object>(ex); } // Determine if we have a faulted task or not and handle it appropriately. return(piplineInvocation.ContinueWithPreservedCulture(task => { if (progress != null) { // Stop ability to send any more progress updates progress.SetComplete(); } if (task.IsFaulted) { return ProcessResponse(tracker, result: null, request: hubRequest, error: task.Exception); } else if (task.IsCanceled) { return ProcessResponse(tracker, result: null, request: hubRequest, error: new OperationCanceledException()); } else { return ProcessResponse(tracker, task.Result, hubRequest, error: null); } }) .FastUnwrap()); }
private static HubInvocationProgress GetProgressInstance(MethodDescriptor methodDescriptor, Func <object, Task> sendProgressFunc, ILogger logger) { HubInvocationProgress progress = null; if (methodDescriptor.ProgressReportingType != null) { progress = HubInvocationProgress.Create(methodDescriptor.ProgressReportingType, sendProgressFunc, logger); } return(progress); }