public void When_disposing_one_of_the_hubs()
        {
            var hub1 = new MessageHub();
            var hub2 = new MessageHub();

            var totalMessages = new List <string>();

            hub1.RegisterGlobalHandler((type, msg) => totalMessages.Add((string)msg));
            hub2.RegisterGlobalHandler((type, msg) => totalMessages.Add((string)msg));

            var hub1Messages = new List <string>();
            var hub2Messages = new List <string>();

            hub1.Subscribe <string>(x => hub1Messages.Add(x));
            hub2.Subscribe <string>(x => hub2Messages.Add(x));

            hub1.Publish("A");

            hub2.Publish("B");
            hub2.Publish("C");

            hub1.Dispose();

            Should.Throw <ObjectDisposedException>(() => hub1.Publish("C"))
            .Message.ShouldBe("Cannot access a disposed object.\r\nObject name: 'The ThreadLocal object has been disposed.'.");

            hub2.Publish("D");

            totalMessages.ShouldBe(new[] { "A", "B", "C", "D" });

            hub1Messages.ShouldBe(new[] { "A" });
            hub2Messages.ShouldBe(new[] { "B", "C", "D" });

            hub2.Dispose();
        }
        public void When_testing_multiple_subscribers_with_publisher_on_current_thread()
        {
            var hub = new MessageHub();

            hub.ClearSubscriptions();

            var queueOne = new List <string>();
            var queueTwo = new List <string>();

            Action <string> subscriberOne = msg => queueOne.Add("Sub1-" + msg);
            Action <string> subscriberTwo = msg => queueTwo.Add("Sub2-" + msg);

            hub.Subscribe(subscriberOne);
            hub.Subscribe(subscriberTwo);

            hub.Publish("MessageA");

            queueOne.Count.ShouldBe(1);
            queueTwo.Count.ShouldBe(1);

            queueOne[0].ShouldBe("Sub1-MessageA");
            queueTwo[0].ShouldBe("Sub2-MessageA");

            hub.Publish("MessageB");

            queueOne.Count.ShouldBe(2);
            queueTwo.Count.ShouldBe(2);

            queueOne[1].ShouldBe("Sub1-MessageB");
            queueTwo[1].ShouldBe("Sub2-MessageB");
        }
Beispiel #3
0
 private void KeyboardListenerOnKeyPressed(object?sender, KeyboardEventArgs e)
 {
     if (e.Key == Keys.Escape)
     {
         messageHub.Publish(new ExitGameMessage());
     }
 }
        public void When_testing_multiple_subscribers_with_filters_and_publisher_on_current_thread()
        {
            var hub = new MessageHub();

            hub.ClearSubscriptions();

            var queueOne = new List <string>();
            var queueTwo = new List <string>();

            var predicateOne = new Predicate <string>(x => x.Length > 3);
            var predicateTwo = new Predicate <string>(x => x.Length < 3);

            Action <string> subscriberOne = msg =>
            {
                if (predicateOne(msg))
                {
                    queueOne.Add("Sub1-" + msg);
                }
            };

            Action <string> subscriberTwo = msg =>
            {
                if (predicateTwo(msg))
                {
                    queueTwo.Add("Sub2-" + msg);
                }
            };

            hub.Subscribe(subscriberOne);
            hub.Subscribe(subscriberTwo);

            hub.Publish("MessageA");

            queueOne.Count.ShouldBe(1);
            queueTwo.Count.ShouldBe(0);
            queueOne[0].ShouldBe("Sub1-MessageA");

            hub.Publish("MA");

            queueTwo.Count.ShouldBe(1);
            queueOne.Count.ShouldBe(1);
            queueTwo[0].ShouldBe("Sub2-MA");

            hub.Publish("MMM");

            queueOne.Count.ShouldBe(1);
            queueTwo.Count.ShouldBe(1);

            hub.Publish("MessageB");

            queueOne.Count.ShouldBe(2);
            queueTwo.Count.ShouldBe(1);
            queueOne[1].ShouldBe("Sub1-MessageB");

            hub.Publish("MB");

            queueTwo.Count.ShouldBe(2);
            queueOne.Count.ShouldBe(2);
            queueTwo[1].ShouldBe("Sub2-MB");
        }
        public void When_using_multiple_hubs()
        {
            var hub1 = new MessageHub();
            var hub2 = new MessageHub();

            var totalMessages = new List <string>();

            hub1.RegisterGlobalHandler((type, msg) => totalMessages.Add((string)msg));
            hub2.RegisterGlobalHandler((type, msg) => totalMessages.Add((string)msg));

            var hub1Messages = new List <string>();
            var hub2Messages = new List <string>();

            hub1.Subscribe <string>(x => hub1Messages.Add(x));
            hub2.Subscribe <string>(x => hub2Messages.Add(x));

            hub1.Publish("A");

            hub2.Publish("B");
            hub2.Publish("C");

            totalMessages.ShouldBe(new [] { "A", "B", "C" });

            hub1Messages.ShouldBe(new [] { "A" });
            hub2Messages.ShouldBe(new [] { "B", "C" });

            hub1.Dispose();
            hub2.Dispose();
        }
        public void When_subscribing_handlers_with_one_throwing_exception()
        {
            var hub = new MessageHub();

            var queue     = new List <string>();
            var totalMsgs = new List <string>();
            var errors    = new List <KeyValuePair <Guid, Exception> >();

            hub.RegisterGlobalHandler((type, msg) =>
            {
                type.ShouldBe(typeof(string));
                msg.ShouldBeOfType <string>();
                totalMsgs.Add((string)msg);
            });

            hub.RegisterGlobalErrorHandler(
                (token, e) => errors.Add(new KeyValuePair <Guid, Exception>(token, e)));

            Action <string> subscriberOne   = msg => queue.Add("Sub1-" + msg);
            Action <string> subscriberTwo   = msg => { throw new InvalidOperationException("Ooops-" + msg); };
            Action <string> subscriberThree = msg => queue.Add("Sub3-" + msg);

            hub.Subscribe(subscriberOne);
            var subTwoToken = hub.Subscribe(subscriberTwo);

            hub.Subscribe(subscriberThree);
            hub.Publish("A");

            Action <string> subscriberFour = msg => { throw new InvalidCastException("Aaargh-" + msg); };
            var             subFourToken   = hub.Subscribe(subscriberFour);

            hub.Publish("B");

            queue.Count.ShouldBe(4);
            queue[0].ShouldBe("Sub1-A");
            queue[1].ShouldBe("Sub3-A");
            queue[2].ShouldBe("Sub1-B");
            queue[3].ShouldBe("Sub3-B");

            totalMsgs.Count.ShouldBe(2);
            totalMsgs.ShouldContain(msg => msg == "A");
            totalMsgs.ShouldContain(msg => msg == "B");

            errors.Count.ShouldBe(3);
            errors.ShouldContain(err =>
                                 err.Value.GetType() == typeof(InvalidOperationException) &&
                                 err.Value.Message == "Ooops-A" &&
                                 err.Key == subTwoToken);

            errors.ShouldContain(err =>
                                 err.Value.GetType() == typeof(InvalidOperationException) &&
                                 err.Value.Message == "Ooops-B" &&
                                 err.Key == subTwoToken);

            errors.ShouldContain(err =>
                                 err.Value.GetType() == typeof(InvalidCastException) &&
                                 err.Value.Message == "Aaargh-B" &&
                                 err.Key == subFourToken);
        }
        public void When_testing_global_on_message_event()
        {
            var hub = new MessageHub();

            hub.ClearSubscriptions();

            var msgOne = 0;

            hub.RegisterGlobalHandler((type, msg) =>
            {
                type.ShouldBe(typeof(string));
                msg.ShouldBeOfType <string>();
                msgOne++;
            });

            hub.Publish("A");

            msgOne.ShouldBe(1);

            hub.ClearSubscriptions();
            hub.Publish("B");

            msgOne.ShouldBe(2);

            var msgTwo = 0;

            hub.RegisterGlobalHandler((type, msg) =>
            {
                type.ShouldBe(typeof(string));
                msg.ShouldBeOfType <string>();
                msgTwo++;
            });

            hub.RegisterGlobalHandler((type, msg) =>
            {
                type.ShouldBe(typeof(string));
                msg.ShouldBeOfType <string>();
                msgTwo++;
            });

            hub.Publish("C");

            msgTwo.ShouldBe(1);

            hub.RegisterGlobalHandler((type, msg) =>
            {
                type.ShouldBe(typeof(string));
                msg.ShouldBeOfType <string>();
                // do nothing with the message
            });

            hub.Publish("D");

            msgOne.ShouldBe(2, "No handler would increment this value");
            msgTwo.ShouldBe(1, "No handler would increment this value");
        }
        public void Test_publish_message_to_messagebus()
        {
            //Arrange
            _mockMessageBus.Setup(b => b.Publish(It.IsAny <string>(), It.IsAny <string>(), null)).Verifiable();

            //Act
            _messageHub.Publish("trace", "{foo:blah}");

            //Assert
            _mockMessageBus.VerifyAll();
        }
Beispiel #9
0
            public void PublishWithStrongReference_ReturnsMessagePublished()
            {
                var messages = new List <SimpleMessageMock>();

                _messageHub.Subscribe <SimpleMessageMock>(messages.Add);
                var message = new SimpleMessageMock(this);

                _messageHub.Publish(message);

                Assert.IsTrue(messages.Any());
                Assert.AreEqual(message, messages.First());
            }
Beispiel #10
0
        public static List <Person> People     = new List <Person>(); //记录客户端
        public void Register(string username)
        {
            ICallBackServices client    = OperationContext.Current.GetCallbackChannel <ICallBackServices>();
            string            sessionid = OperationContext.Current.SessionId;

            OperationContext.Current.Channel.Closing += new EventHandler(Channel_Closing);//注册客户端关闭触发事件
            Person p = new Person(username, sessionid, client);

            People.Add(p);
            hubadd.Publish("刷新");
            p.CallBackmessage.Myname(p);
        }
Beispiel #11
0
        public void Handlers_survive_exceptions()
        {
            var handler = new ThrowingHandler();
            var hub     = new MessageHub();

            hub.Subscribe(handler);

            hub.Publish(new InheritedMessage());
            Assert.Equal(1, handler.Handled);

            hub.Publish(new InheritedMessage());
            Assert.Equal(2, handler.Handled);
        }
Beispiel #12
0
    private EventBasedNetListener CreateServerListener()
    {
        var serverListener = new EventBasedNetListener();

        serverListener.ConnectionRequestEvent += request => { request.Accept(); };
        serverListener.PeerConnectedEvent     += OnPeerConnected;
        serverListener.NetworkReceiveEvent    += (peer, reader, method) => {
            // Console.WriteLine("Server received: {0}", reader.GetString(100));
            if (reader.TryGetByte(out var b))
            {
                switch ((NetMessageType)b)
                {
                case NetMessageType.FullGameStateAck:
                    statusByPeer[peer] = PeerStatus.Joined;
                    break;

                case NetMessageType.JoinGameRequest: {
                    var msg = serializer.Deserialize <JoinGameNetMessage>(reader.GetRemainingBytes());
                    OnPlayerJoining(peer, msg.PlayerCount);
                    break;
                }

                case NetMessageType.PlayerInputs: {
                    var msg = serializer.Deserialize <InputUpdateNetMessage>(reader.GetRemainingBytes());
                    messageHub.Publish(new ReceivedInputMessage(msg.PlayerNumber, msg.Input));
                    break;
                }
                }
            }
        };
        serverListener.PeerDisconnectedEvent += (peer, info) => {
            Console.WriteLine("Peer disconnected {0}, {1}", peer, info);
            messageHub.Publish(new PlayerLeftMessage(peer.Id));
        };
        serverListener.NetworkReceiveUnconnectedEvent += (endPoint, reader, type) => {
            if (endPoint.AddressFamily == AddressFamily.InterNetwork && type == UnconnectedMessageType.Broadcast)
            {
                if (reader.TryGetByte(out var b))
                {
                    switch ((NetMessageType)b)
                    {
                    case NetMessageType.ListServersRequest: {
                        netServer.SendUnconnectedMessage(new[] { (byte)NetMessageType.ListServersResponse }, endPoint);
                        break;
                    }
                    }
                }
            }
        };
        return(serverListener);
    }
Beispiel #13
0
        /// <summary>
        /// Called when [user interface loaded].
        /// </summary>
        /// <param name="payload">The payload.</param>
        /// <returns></returns>
        private async Task OnUserInterfaceLoaded(object payload)
        {
            try
            {
                IsUserInterfaceEnabled = false;
                MessageHub.Publish(MessageNames.StatusAvailable, "Loading Pictures . . .");
                var pictures = await StoreProvider.RetrievePictureHeadersAsync();

                foreach (var p in pictures)
                {
                    PictureHeaders.Add(p);
                }

                MessageHub.Publish(MessageNames.StatusAvailable, "Ready");
            }
            catch (Exception ex)
            {
                // We send a status message to the hub but it should really be an Error message of its own type
                MessageHub.Publish(MessageNames.StatusAvailable, $"Error: {ex.Message}");
            }
            finally
            {
                IsUserInterfaceEnabled = true;
            }
        }
Beispiel #14
0
        public void Publishes_to_multicast_handlers()
        {
            var hub = new MessageHub();

            var baseCalled      = 0;
            var inheritedCalled = 0;

            void Handler1(BaseMessage e)
            {
                baseCalled++;
            }

            void Handler2(InheritedMessage e)
            {
                inheritedCalled++;
            }

            hub.Subscribe((Action <BaseMessage>)Handler1);
            hub.Subscribe((Action <InheritedMessage>)Handler2);

            // one handler, many events (by virtue of class hierarchy)
            var sent = hub.Publish(new InheritedMessage {
                Id = 123, Value = "ABC"
            });

            Assert.True(sent);
            Assert.Equal(1, inheritedCalled);
            Assert.Equal(1, baseCalled);
        }
Beispiel #15
0
        public void Can_subscribe_with_multiple_hierarchical_consumers()
        {
            var hub = new MessageHub();

            var handler1 = new ManifoldHierarchicalMessageHandler();
            var handler2 = new ManifoldHierarchicalMessageHandler();
            var handler3 = new ManifoldHierarchicalMessageHandler();

            hub.Subscribe <IMessage>(handler1);
            hub.Subscribe <BaseMessage>(handler2);
            hub.Subscribe <InheritedMessage>(handler3);

            var sent = hub.Publish(new InheritedMessage());

            Assert.True(sent);

            Assert.Equal(1, handler1.HandledInterface);
            Assert.Equal(0, handler1.HandledBase);
            Assert.Equal(0, handler1.HandledInherited);

            Assert.Equal(0, handler2.HandledInterface);
            Assert.Equal(1, handler2.HandledBase);
            Assert.Equal(0, handler2.HandledInherited);

            Assert.Equal(0, handler3.HandledInterface);
            Assert.Equal(0, handler3.HandledBase);
            Assert.Equal(1, handler3.HandledInherited);
        }
Beispiel #16
0
        public static void HubMultiplePublisherSingleSubscriberAndGlobalAuditHandler()
        {
            long globalCount = 0;
            long result      = 0;
            var  hub         = new MessageHub();

            hub.RegisterGlobalHandler((type, msg) => Interlocked.Increment(ref globalCount));

            Action <string> subscriber = msg => Interlocked.Increment(ref result);

            hub.Subscribe(subscriber);

            var    sw     = Stopwatch.StartNew();
            Action action = () =>
            {
                while (sw.Elapsed < Duration)
                {
                    hub.Publish("Hello there!");
                }
            };

            Parallel.Invoke(action, action, action, action, action);

            Console.WriteLine($"Result is: {result:n0} Time Taken: {sw.Elapsed}");
        }
Beispiel #17
0
        /// <summary>
        /// Called when [selected picture header].
        /// </summary>
        /// <param name="payload">The payload.</param>
        /// <returns></returns>
        private async Task OnSelectedPictureHeader(object payload)
        {
            try
            {
                IsUserInterfaceEnabled = false;
                var picHeader = payload as PictureHeaderViewModel;
                MessageHub.Publish(MessageNames.StatusAvailable, $"Loading selected {picHeader.Name}, Taken on {picHeader.DateTakenUtc}");
                if (picHeader == null)
                {
                    return;
                }

                // Save the picture before switching it.
                if (CurrentPicture != null)
                {
                    await StoreProvider.AddOrUpdatePictureAsync(CurrentPicture);
                }

                CurrentPicture = await StoreProvider.LoadPictureAsync(picHeader.PictureId);

                MessageHub.Publish(MessageNames.StatusAvailable, "Ready");
            }
            catch (Exception ex)
            {
                // We send a status message to the hub but it should really be an Error message of its own type
                MessageHub.Publish(MessageNames.StatusAvailable, $"Error: {ex.Message}");
            }
            finally
            {
                IsUserInterfaceEnabled = true;
            }
        }
        public void When_subscribing_same_handler_multiple_times()
        {
            var hub = new MessageHub();

            var totalMsgCount = 0;

            hub.RegisterGlobalHandler((type, msg) =>
            {
                type.ShouldBe(typeof(string));
                msg.ShouldBeOfType <string>();
                Interlocked.Increment(ref totalMsgCount);
            });

            var             queue      = new ConcurrentQueue <string>();
            Action <string> subscriber = msg => queue.Enqueue(msg);

            var tokenOne = hub.Subscribe(subscriber);
            var tokenTwo = hub.Subscribe(subscriber);

            hub.IsSubscribed(tokenOne);
            hub.IsSubscribed(tokenTwo);

            hub.Publish("A");

            queue.Count.ShouldBe(2);
            totalMsgCount.ShouldBe(1);
        }
        public void Should_send_to_other_clients_when_one_fails()
        {
            // One client may throw in OnNext, but observable should not fail and continue sending
            WithCheckpointStorageService(storageService =>
            {
                var hubContext = Substitute.For <IHubContext <CheckpointsHub> >();
                var log        = new List <string>();

                hubContext.Clients.Client("con1")
                .SendCoreAsync(Arg.Any <string>(), Arg.Any <object[]>())
                .ThrowsForAnyArgs(x => new ArgumentOutOfRangeException())
                .AndDoes(info => log.Add("thrown"));

                hubContext.Clients.Client("con2")
                .SendCoreAsync("Checkpoint", Arg.Any <object[]>())
                .Returns(Task.CompletedTask)
                .AndDoes(info => log.Add(info.ArgAt <object[]>(1)
                                         .OfType <Checkpoint[]>().First()[0].RiderId));

                var ds = new DistributionService(hubContext, MessageHub, storageService);
                ds.StartStream("con1", DateTime.UtcNow);
                ds.StartStream("con2", DateTime.UtcNow);


                MessageHub.Publish(new Checkpoint("r1", Constants.DefaultUtcDate));


                new Timing().Logger(Logger).Expect(() => log.Count >= 2);
                log[0].Should().Be("thrown");
                log[1].Should().Be("r1");
            });
        }
Beispiel #20
0
        public static void HubSinglePublisherMultipleSubscriberThrottled()
        {
            long counter    = 0;
            var  messageAgg = new MessageHub();

            messageAgg.RegisterGlobalHandler((type, msg) =>
            {
                Console.WriteLine($"Global: {DateTime.UtcNow:hh:mm:ss.fff} - {msg.ToString()}");
            });

            Action <long> subscriber = msg =>
            {
                Console.WriteLine($"Subscriber: {DateTime.UtcNow:hh:mm:ss.fff} - {msg.ToString()}");
            };

            messageAgg.Subscribe(subscriber, TimeSpan.FromSeconds(1));

            var sw = Stopwatch.StartNew();

            while (sw.Elapsed < Duration)
            {
                messageAgg.Publish(counter++);
                Thread.Sleep(100);
            }
        }
        public void When_testing_multiple_subscribers_with_one_subscriber_unsubscribing_then_resubscribing()
        {
            var totalMessages = 0;
            var hub           = new MessageHub();

            hub.ClearSubscriptions();

            hub.RegisterGlobalHandler((type, msg) =>
            {
                type.ShouldBe(typeof(string));
                msg.ShouldBeOfType <string>();
                Interlocked.Increment(ref totalMessages);
            });

            var queue = new List <string>();

            Action <string> subscriberOne = msg => queue.Add("Sub1-" + msg);
            Action <string> subscriberTwo = msg => queue.Add("Sub2-" + msg);

            var tokenOne = hub.Subscribe(subscriberOne);

            hub.Subscribe(subscriberTwo);

            hub.Publish("A");

            queue.Count.ShouldBe(2);
            queue[0].ShouldBe("Sub1-A");
            queue[1].ShouldBe("Sub2-A");

            hub.Unsubscribe(tokenOne);

            hub.Publish("B");

            queue.Count.ShouldBe(3);
            queue[2].ShouldBe("Sub2-B");

            hub.Subscribe(subscriberOne);

            hub.Publish("C");

            queue.Count.ShouldBe(5);
            queue[3].ShouldBe("Sub2-C");
            queue[4].ShouldBe("Sub1-C");

            Thread.Sleep(TimeSpan.FromSeconds(1));
            totalMessages.ShouldBe(3);
        }
Beispiel #22
0
        public void Publishes_to_multicast_handlers_with_interfaces_with_concrete_consumer()
        {
            var handler = new IncrementingHandler();
            var hub     = new MessageHub();

            hub.Subscribe(handler);
            hub.Publish(new InheritedMessage());
            Assert.Equal(1, handler.Handled);
        }
        public void When_publishing_with_no_subscribers()
        {
            var hub = new MessageHub();

            Should.NotThrow(() => hub.Publish(TimeSpan.FromTicks(1234)));

            string result = null;

            hub.RegisterGlobalHandler((type, msg) =>
            {
                type.ShouldBe(typeof(string));
                msg.ShouldBeOfType <string>();
                result = msg as string;
            });

            hub.Publish("654321");
            result.ShouldBe("654321");
        }
Beispiel #24
0
    void Start()
    {
        if (continuesSpawn)
        {
            StartCoroutine(StartSpawmDelay(startDelay));
        }

        MessageHub.Publish(new NewSpawner(this));
    }
Beispiel #25
0
    public void Spawn()
    {
        var spawnPosition = transform.position;

        spawnPosition.z += 1;
        var obj = Instantiate(objToSpawn, spawnPosition, Quaternion.identity) as GameObject;

        MessageHub.Publish(new NewSpawnEvent(this, obj));
        ExecuteEvents.Execute <ISpawnerMessageTarget>(transform.gameObject, null, (x, y) => x.NewSpawn(obj));
    }
Beispiel #26
0
        public void Handlers_can_return_false_safely()
        {
            var handler = new FailingHandler();
            var hub     = new MessageHub();

            hub.Subscribe(handler);

            var result = hub.Publish(new InheritedMessage());

            Assert.Equal(1, handler.Handled);
            Assert.False(result);
        }
Beispiel #27
0
        public void PublishMessageWhenUnsubscribed_MessageNotPublished()
        {
            var hub     = new MessageHub();
            var list    = new List <SimpleMessageMock>();
            var message = new SimpleMessageMock(this);
            var token   = hub.Subscribe <SimpleMessageMock>(list.Add);

            hub.Unsubscribe <SimpleMessageMock>(token);
            hub.Publish(message);

            Assert.IsFalse(list.Any());
        }
Beispiel #28
0
        public void Can_handle_error_with_callback()
        {
            var errors = 0;

            var hub = new MessageHub();

            var sent = false;

            // SubscribeWithDelegate:
            {
                hub.Subscribe <InheritedMessage>(e => throw new Exception(), (m, ex) => { errors++; });
                object @event = new InheritedMessage {
                    Id = 123, Value = "ABC"
                };
                sent = hub.Publish(@event);
                Assert.False(sent, "publishing an exception should bubble as false to the publish result");
                Assert.Equal(1, errors);
            }

            // Subscribe (manifold):
            {
                var handler = new ManifoldHierarchicalMessageHandler();
                hub.Subscribe(handler, (m, ex) => { errors++; });
                sent = hub.Publish(new ErrorMessage {
                    Error = true
                });
                Assert.False(sent);
                Assert.Equal(2, errors);
            }

            // SubscribeWithInterface:
            {
                hub.Subscribe(new ThrowingHandler());
                sent = hub.Publish(new ErrorMessage {
                    Error = true
                });
                Assert.False(sent);
                Assert.Equal(3, errors);
            }
        }
        public void When_testing_single_subscriber_with_publisher_on_current_thread()
        {
            var hub = new MessageHub();

            hub.ClearSubscriptions();

            var queue = new List <string>();

            Action <string> subscriber = msg => queue.Add(msg);

            hub.Subscribe(subscriber);

            hub.Publish("MessageA");

            queue.Count.ShouldBe(1);
            queue[0].ShouldBe("MessageA");

            hub.Publish("MessageB");

            queue.Count.ShouldBe(2);
            queue[1].ShouldBe("MessageB");
        }
Beispiel #30
0
        public void Can_publish_events_by_type()
        {
            var handled = 0;
            var hub     = new MessageHub();

            hub.Subscribe <InheritedMessage>(e => handled++);
            object @event = new InheritedMessage {
                Id = 123, Value = "ABC"
            };
            var sent = hub.Publish(@event);

            Assert.True(sent, "did not send event to a known subscription");
            Assert.Equal(1, handled);
        }