示例#1
0
        protected override Task OnReceivedAsync(string clientId, 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(clientId, _cookies, _user);
            hub.Caller  = new SignalAgent(Connection, clientId, hubName, state);
            var agent = new ClientAgent(Connection, hubName);

            hub.Agent        = agent;
            hub.GroupManager = agent;

            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)));
                    }
                    else
                    {
                        // Get the <T> in Task<T>
                        Type resultType = returnType.GetGenericArguments().Single();

                        // Get the correct ContinueWith overload
                        var continueWith = (from m in task.GetType().GetMethods()
                                            let methodParameters = m.GetParameters()
                                                                   where m.Name.Equals("ContinueWith", StringComparison.OrdinalIgnoreCase) &&
                                                                   methodParameters.Length == 1
                                                                   let parameter = methodParameters[0]
                                                                                   where parameter.ParameterType.IsGenericType &&
                                                                                   typeof(Action <>) == parameter.ParameterType.GetGenericTypeDefinition()
                                                                                   select new
                        {
                            Method = m,
                            ArgType = parameter.ParameterType.GetGenericArguments()[0]
                        })
                                           .FirstOrDefault();

                        var taskParameter       = Expression.Parameter(continueWith.ArgType);
                        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.ArgType), continueWith.Method, lambda);
                        return(Expression.Lambda <Func <Task> >(call).Compile()());
                    }
                }
                else
                {
                    ProcessResult(state, result, hubRequest, null);
                }
            }
            catch (TargetInvocationException e)
            {
                ProcessResult(state, null, hubRequest, e);
            }

            return(base.OnReceivedAsync(clientId, data));
        }
示例#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(_context, connectionId);
            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("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 = ProcessResult(state, result, hubRequest, null);
                }
            }
            catch (TargetInvocationException e)
            {
                resultTask = ProcessResult(state, null, hubRequest, e);
            }

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