public void InvokeCallbacksWith(PublishingTopic publishingTopic, T message)
 {
     //note: I would also change the delegate to accept SubscriptionTopic rather than generic built in string type, which doesn't distinguish between SubscriptionTopic and PublishingTopic
     _subscribers
     .Values
     .ToList()
     .ForEach(callback => callback.Invoke(publishingTopic.AsString(), message));
 }
        /// <summary>
        /// Publishes the message to specified topic.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="topicAsString">The topic.</param>
        /// <exception cref="InvalidTopicException"></exception>
        public void Publish(string topicAsString, T message)
        {
            //note: I'd rather pass strongly typed PublishingTopic as the parameter, but in order to not change the original tests, I did the conversion here; same goes for Subscribe method
            var publishingTopic = PublishingTopic.From(topicAsString);

            _subscribers
            .Matching(publishingTopic)
            .InvokeCallbacksWith(publishingTopic, message);
        }
        public bool Matches(PublishingTopic publishingTopic)
        {
            if (_levels.HasMoreElementsThan(publishingTopic.AsLevels()))
            {
                return(false);
            }

            return(_levels
                   .Zip(publishingTopic.AsLevels(), (first, second) => first.Matches(second))
                   .All(isMatching => isMatching));
        }
 public Subscribers <T> Matching(PublishingTopic publishingTopic)
 {
     return(new Subscribers <T>(_subscribers
                                .Where(sub => sub.Key.Matches(publishingTopic))
                                .ToDictionary(x => x.Key, x => x.Value)));
 }