Example #1
0
        /// <summary>
        /// 客户端连接时调用。继承后需要确保 <c>base.OnConnected()</c> 得到调用。
        /// </summary>
        public override async Task OnConnected()
        {
            var mqChannel = Global.Container.GetInstance <MqClientProvider>().CreateModel();

            MqChannels[Context.ConnectionId] = mqChannel;
            var logger    = Global.Container.GetInstance <LogProvider <ReliableHub <TClient> > >().Logger;
            var userId    = Context.User.Identity.GetUserId();
            var queueName = MqClientProvider.ReliableNotificationQueue(userId, GetType().Name);

            mqChannel.QueueDeclare(queueName, true, false, false, null);
            var consumer = new EventingBasicConsumer(mqChannel);

            consumer.Received += (sender, args) =>
            {
                try
                {
                    using (var streamReader = new StreamReader(new MemoryStream(args.Body)))
                    {
                        var serializer   = new JsonSerializer();
                        var notification =
                            serializer.Deserialize <ReliableNotificationDto>(new JsonTextReader(streamReader));
                        typeof(TClient).GetMethod(notification.MethodName)
                        .Invoke(Clients.User(userId), notification.Arguments.Select(a =>
                        {
                            var argumentType = Type.GetType(a.Type);
                            if (argumentType == null)
                            {
                                return(null);
                            }
                            var value = a.Value as JToken;
                            return(value != null ? value.ToObject(argumentType) : a.Value);
                        }).ToArray());
                        mqChannel.BasicAck(args.DeliveryTag, false);
                    }
                }
                catch (Exception e)
                {
                    mqChannel.BasicNack(args.DeliveryTag, false, false);
                    logger.Fatal("Unhandled MQ consumer exception.", e);
                }
            };
            mqChannel.BasicConsume(queueName, false, consumer);
            await base.OnConnected();
        }
Example #2
0
        /// <summary>
        /// 对指定用户发出通知,并保证通知送达(如果用户当前不在线则存储通知,下次上线时发送)
        /// </summary>
        /// <param name="userId">用户 ID</param>
        /// <param name="clientActionExpression">通知发送表达式</param>
        /// <typeparam name="THub">Hub 类型</typeparam>
        /// <typeparam name="TClient">Hub Client 类型</typeparam>
        public void ReliableNotify <THub, TClient>(string userId,
                                                   Expression <Action <TClient> > clientActionExpression)
            where THub : ReliableHub <TClient>
            where TClient : class
        {
            var methodCallExpression = (MethodCallExpression)clientActionExpression.Body;
            var hubType = typeof(THub);
            var dto     = new ReliableNotificationDto
            {
                MethodName = methodCallExpression.Method.Name,
                Arguments  = methodCallExpression.Arguments
                             .Select(argument => new ReliableNotificationArgumentDto
                {
                    Type  = $"{argument.Type.FullName}, {argument.Type.Assembly.GetName().Name}",
                    Value = Expression.Lambda(argument).Compile().DynamicInvoke()
                })
                             .ToList()
            };
            var queueName = MqClientProvider.ReliableNotificationQueue(userId, hubType.Name);

            _mqChannel.QueueDeclare(queueName, true, false, false, null);
            _mqChannel.SendMessage(string.Empty, queueName, dto);
        }