public void Notify(NotificationMessage notificationMessage)
        {
            var notificationId = ++_lastNotificationId;
            if (notificationId <= 0)
                notificationId = _lastNotificationId = 1;

            notificationMessage.NotificationId = notificationId;

            var sender = ActorCell.GetCurrentSelfOrNoSender();
            Receiver.Tell(notificationMessage, sender);
        }
Exemple #2
0
        private void OnNotificationMessage(NotificationMessage notification)
        {
            object observerContext = null;

            if (notification.ObserverId != 0)
            {
                observerContext = EnsureObserverMap().GetContext(notification.ObserverId);
                if (observerContext == null)
                {
                    // because it could be a removed observer, doesn't log anything.
                    return;
                }
            }

            if (notification.InvokePayload == null)
            {
                Context.System.EventStream.Publish(new Event.Warning(
                                                       Self.Path.ToString(), GetType(),
                                                       $"Receives a bad notification with no payload from {Sender}"));
                return;
            }

            var payloadType = notification.InvokePayload.GetType();
            var handlerItem = _handler.NotificationDispatcher.GetHandler(payloadType);

            if (handlerItem == null)
            {
                // if generic argument, try to instantiate a generic handler by the given payload type.

                if (payloadType.IsGenericType)
                {
                    var genericHandlerItem = _handler.NotificationDispatcher.GetHandler(payloadType.GetGenericTypeDefinition());
                    if (genericHandlerItem != null)
                    {
                        handlerItem = genericHandlerItem.GenericHandlerBuilder(payloadType);
                        _handler.NotificationDispatcher.AddHandler(payloadType, handlerItem);
                    }
                }

                // oops, no handler.

                if (handlerItem == null)
                {
                    Context.System.EventStream.Publish(new Event.Warning(
                                                           Self.Path.ToString(), GetType(),
                                                           $"Cannot find a handler for notification {notification.InvokePayload.GetType()} from {Sender}"));
                    return;
                }
            }

            if (handlerItem.Handler != null)
            {
                // sync handle

                try
                {
                    _observerContext = observerContext;
                    handlerItem.Handler(this, notification);
                }
                finally
                {
                    _observerContext = null;
                }
            }
            else
            {
                // async handle

                var context = new MessageHandleContext {
                    Self = Self, Sender = base.Sender, CancellationToken = CancellationToken, ObserverContext = observerContext
                };
                if (handlerItem.IsReentrant)
                {
                    _activeReentrantCount += 1;
                }
                else
                {
                    BecomeStacked(OnReceiveInAtomicTask);
                    _currentAtomicContext = context;
                }

                using (new SynchronizationContextSwitcher(new ActorSynchronizationContext(context)))
                {
                    handlerItem.AsyncHandler(this, notification)
                    .ContinueWith(t => OnTaskCompleted(t.Exception, handlerItem.IsReentrant),
                                  TaskContinuationOptions.ExecuteSynchronously);
                }
            }
        }